Skip to content

Commit

Permalink
[SIMPLE LANG] adding any amount of arguments (... in c) +[DEBUG] addi…
Browse files Browse the repository at this point in the history
…ng debugging print
  • Loading branch information
Cr0a3 committed Aug 23, 2024
1 parent 199bd9a commit dd9f492
Show file tree
Hide file tree
Showing 13 changed files with 106 additions and 24 deletions.
9 changes: 9 additions & 0 deletions src/IR/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ pub struct FunctionType {
pub args: Vec<(/*num*/usize, TypeMetadata)>,
/// The return type
pub ret: TypeMetadata,
/// After the given arguments any argument type can be supplied (like the printf function - is in c ...)
pub any_args: bool,
}

impl FunctionType {
Expand All @@ -35,9 +37,16 @@ impl FunctionType {
ret
},
ret: ret,
any_args: false,
}
}

/// Activates dynamic arguments
/// Makes that you can supply any argument after the fixed given arguments
pub fn activate_dynamic_arguments(&mut self) {
self.any_args = true;
}

/// Returns the argument as a var
/// If the num doesn't exists, it panics
pub fn arg(&self, num: usize) -> Var {
Expand Down
12 changes: 10 additions & 2 deletions src/IR/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -631,10 +631,18 @@ impl Ir for Call<Function, Vec<Var>, Var> {
}

let mut index = 0;
let args = &self.inner1.ty.args;
for arg in &self.inner2 {
if matches!(self.inner1.ty.args.get(index), Some((_, argty)) if *argty != (*arg).ty.into()) {
Err(VerifyError::IDontWantToAddAnErrorMessageHereButItsAnError)?
if index < args.len() {
if matches!(args.get(index), Some((_, argty)) if *argty != (*arg).ty.into()) {
Err(VerifyError::InvalidArgumentTypeFound)?
}
} else {
if !self.inner1.ty.any_args {
Err(VerifyError::ToManyArgumentsWereSupplyed)?
}
}

index += 1;
}

Expand Down
17 changes: 13 additions & 4 deletions src/IR/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ pub enum VerifyError {
RetTyNotFnTy(TypeMetadata, TypeMetadata),
/// The type of op0 operand doesn't match the type of the op1 operand
Op0Op1TyNoMatch(TypeMetadata, TypeMetadata),
/// I am to lazy to add an error message here
IDontWantToAddAnErrorMessageHereButItsAnError,
/// The given argument type doesn't overllap with the actual argument type
InvalidArgumentTypeFound,
/// To many arguments were supplyed
ToManyArgumentsWereSupplyed,
}

impl Display for VerifyError {
Expand All @@ -47,8 +49,15 @@ impl Display for VerifyError {
)

},
VerifyError::IDontWantToAddAnErrorMessageHereButItsAnError => {
"i am to lazy to add an useful error message here. go ahed and create an github issue".to_string()
VerifyError::InvalidArgumentTypeFound => {
format!(
"an unexpected argument type was found"
)
},
VerifyError::ToManyArgumentsWereSupplyed => {
format!(
"too many arguments were supplyed"
)
}
})
}
Expand Down
15 changes: 13 additions & 2 deletions src/IR/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,14 @@ impl Module {
lines.push_str("section .rodata\n\n");

for (_, consta) in &self.consts {
lines.push_str(&format!("{}: {:?}\n", consta.name, consta.data));
lines.push_str(&format!("{}: {:?} # {}\n", consta.name, consta.data, consta.data.iter()
.filter_map(|&byte| {
if byte >= 32 && byte <= 126 {
Some(byte as char)
} else {
None
}
}).collect::<String>()));
}
lines.push_str("section .text\n\n");

Expand All @@ -206,12 +213,16 @@ impl Module {

for block in &func.blocks {
if block.name.to_lowercase() != "entry" {
lines += &format!(" {}:\n", block.name)
lines += &format!("\t.{}:\n", block.name)
}

let asm_lines = registry.buildAsmForTarget(triple, block, func)?;

for line in asm_lines {
if line.starts_with("#") { // debug
lines.pop(); // \n
}

lines += &format!("\t{}\n", line);
}
}
Expand Down
16 changes: 12 additions & 4 deletions src/Target/x64/asm/instr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@ impl Instr {

if let Some(Operand::Reg(op0)) = &self.op1 {
let op0 = op0.as_any().downcast_ref::<x64Reg>().expect("expected x64 registers and not the ones from other archs");

println!("mov r, r");


if op0.extended() {
rex.b = true;
}
Expand Down Expand Up @@ -327,6 +325,7 @@ impl Instr {
(vec![], None)
}
}
Mnemonic::Debug => (vec![], None),
})
}

Expand Down Expand Up @@ -406,7 +405,7 @@ impl Instr {
}
}
}
Mnemonic::Link => {},
Mnemonic::Link | Mnemonic::Debug => {},
Mnemonic::Endbr64 => {
if self.op1.is_some() || self.op2.is_some() {
Err(InstrEncodingError::InvalidVariant(self.clone(), "endbr64 can't have operands".to_string()))?
Expand Down Expand Up @@ -437,13 +436,15 @@ impl Instr {
Operand::Reg(reg) => profile.markup(&reg.to_string(), ColorClass::Var),
Operand::Mem(mem) => profile.markup(&format!("{}", mem), ColorClass::Var),
Operand::LinkDestination(_, _) => "".to_string(),
Operand::Debug(s) => s.to_string(),
}));
if let Some(op2) = &self.op2 {
string.push_str(&format!(", {}", match op2 {
Operand::Imm(num) => profile.markup(&format!("{}", num.to_string()), ColorClass::Value),
Operand::Reg(reg) => profile.markup(&format!(", {}", reg.to_string()), ColorClass::Var),
Operand::Mem(mem) => profile.markup(&format!("{}", mem), ColorClass::Var),
Operand::LinkDestination(_, _) => "".to_string(),
Operand::Debug(s) => s.to_string(),
}));
}
}
Expand Down Expand Up @@ -556,6 +557,8 @@ pub enum Mnemonic {

/// here's a link placed
Link,
/// for debugging pourpusis
Debug,
}

impl FromStr for Mnemonic {
Expand Down Expand Up @@ -602,6 +605,7 @@ impl Display for Mnemonic {
Mnemonic::Jmp => "jmp",
Mnemonic::Endbr64 => "endbr64",
Mnemonic::Link => "",
Mnemonic::Debug => "#",
})
}
}
Expand All @@ -617,6 +621,8 @@ pub enum Operand {
Mem(MemOp),
/// The link destination
LinkDestination(String, i64),
//// For debugging pourpusis
Debug(String),
}

impl PartialEq for Operand {
Expand All @@ -626,6 +632,7 @@ impl PartialEq for Operand {
(Self::Reg(l0), Self::Reg(r0)) => l0 == r0,
(Self::Mem(l0), Self::Mem(r0)) => l0 == r0,
(Self::LinkDestination(l0, l1), Self::LinkDestination(r0, r1)) => l0 == r0 && l1 == r1,
(Self::Debug(l0), Self::Debug(r0)) => l0 == r0,
_ => false,
}
}
Expand All @@ -638,6 +645,7 @@ impl Display for Operand {
Operand::Reg(reg) => reg.to_string(),
Operand::Mem(mem) => format!("{}", mem),
Operand::LinkDestination(_, _) => "".to_string(),
Operand::Debug(s) => s.to_string(),
})
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Target/x64/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ pub(crate) fn buildAsmX86<'a>(block: &'a Block, func: &Function, call: &CallConv
for node in &block.nodes {
let compiled = node.compile(registry);
out.extend(compiled);
out.push_back(Instr::with1(Mnemonic::Debug, Operand::Debug(format!("{}", node.dump()))));
}

registry.block = None;
Expand Down
1 change: 1 addition & 0 deletions tools/simplelang/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub struct FnStmt {

pub extrn: bool,
pub import: bool,
pub dynamic_args: bool,
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
6 changes: 6 additions & 0 deletions tools/simplelang/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ impl CodeGenerator {

let mut builder = IRBuilder();

if func.dynamic_args {
func_ty.activate_dynamic_arguments();
}

let mut fun = Func(func.name.to_string(), func_ty);

if func.extrn {
Expand Down Expand Up @@ -161,6 +165,8 @@ impl CodeGenerator {
fn gen_string(&mut self, builder: &mut IRBuilder, string: &String) -> Var {
let constant = self.module.addConst(&format!(".const{}", self.const_index));

self.const_index += 1;

let mut string = string.clone();
string.push('\0');

Expand Down
9 changes: 4 additions & 5 deletions tools/simplelang/example.sl
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ HOW TO RUN:

*/

import with (fmt: string) printf // printf from libc
import with (fmt: string, ...) printf // printf from libc

extern with () main: {
var x: string = "Hello World!";
printf("Hello World!\n");

x += 6;
x -= 4;
var x: u32 = 5;

printf(x);
printf("%d = %d", x, 5);

return 0;
}
3 changes: 3 additions & 0 deletions tools/simplelang/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ pub enum Token {
#[token(":")]
DoubleDot,

#[token("...")]
TripleDot,

#[token("return")]
Return,

Expand Down
2 changes: 1 addition & 1 deletion tools/simplelang/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub fn main() -> Result<(), Box<dyn Error>> {
};

let _tmp;
err!(_tmp, "{:?}", error);
err!(_tmp, "{}", error);
exit(-1);
}
}
Expand Down
12 changes: 12 additions & 0 deletions tools/simplelang/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,24 @@ impl Parser {

let mut args = vec![];

let mut dynamic_args = false;

loop {
match self.tokens.front()? {
Token::Ident(_) => args.push(Expr::Var(self.parse_var()?)),
Token::TripleDot => {
dynamic_args = true;
self.tokens.pop_front();
},
Token::RParam => break,
_ => { return None; },
}

if let Some(Token::Comma) = self.tokens.front() {
if dynamic_args {
err!(self.error, "after a any arg indicator (...) no arguments are allowed to be there");
return None;
}
self.tokens.pop_front();
}
}
Expand All @@ -101,6 +111,7 @@ impl Parser {
args: args,
extrn: false,
import: import,
dynamic_args: dynamic_args,
}))
}

Expand Down Expand Up @@ -137,6 +148,7 @@ impl Parser {
body: body,
args: args,
extrn: extrn,
dynamic_args: dynamic_args,
import: false, // we handled imported functions earlier
}))

Expand Down
27 changes: 21 additions & 6 deletions tools/simplelang/semnatic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{ast::*, err, warn};
pub struct Semnatic {
stmts: VecDeque<Statement>,

funcs: HashMap<String, (/*args*/Vec<Expr>, /*body*/Vec<Expr>)>,
funcs: HashMap<String, (/*args*/Vec<Expr>, /*body*/Vec<Expr>, /*dynamic amount of args*/bool)>,

in_binary: bool,

Expand Down Expand Up @@ -50,13 +50,23 @@ impl Semnatic {

fn analyze_func(&mut self, func: &FnStmt) {
if self.funcs.contains_key(&func.name) {
err!(self.error, "func {:?} defined twice", func.name);
err!(self.error, "func {} defined twice", func.name);
return;
}

let mut vars = HashMap::new();
let mut args = vec![];

if func.import && func.body.len() > 0 {
err!(self.error, "imported functions aren't allowed to have a body but {} has", func.name);
return;
}

if func.dynamic_args && !func.import {
err!(self.error, "only imported functions are allowed to have a variable amount of arguments. But func {} has", func.name);
return;
}

for arg in &func.args {
match arg {
Expr::Var(var) => {
Expand All @@ -76,7 +86,7 @@ impl Semnatic {
return;
}

self.funcs.insert(func.name.to_string(), (args, vec![]));
self.funcs.insert(func.name.to_string(), (args, vec![], func.dynamic_args));
return;
}

Expand Down Expand Up @@ -172,13 +182,18 @@ impl Semnatic {
return;
}

let (args, _) = self.funcs.get(&call.name).unwrap();
let (args, _, dynamic) = self.funcs.get(&call.name).unwrap();

let args = args.len();
let given = call.args.len();

if args != given {
err!(self.error, "expected {} arguments found {}", args, given);
if args != given && !dynamic {
err!(self.error, "expected {} argument(s) found {}", args, given);
return;
}

if args > given {
err!(self.error, "too few arguments were supplyed (expected {} found {})", args, given);
return;
}

Expand Down

0 comments on commit dd9f492

Please sign in to comment.