diff --git a/libbeaker.so b/libbeaker.so new file mode 100755 index 0000000..dfafb60 Binary files /dev/null and b/libbeaker.so differ diff --git a/src/cli.rs b/src/cli.rs index 382b955..be73892 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -22,6 +22,10 @@ pub struct CliArgs { /// Linker args #[arg(long, short='L')] pub linker_args: Vec, + + /// Link with C libs, required for any C libraries + #[arg(long, short='C')] + pub link_c: bool, /// All input files #[clap(num_args = 1..)] diff --git a/src/common/loc.rs b/src/common/loc.rs index 0b15bce..f5c88d7 100644 --- a/src/common/loc.rs +++ b/src/common/loc.rs @@ -1,6 +1,6 @@ use std::fmt::{Debug, Display}; -#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)] +#[derive(Debug, Clone, PartialOrd, Ord, Eq, Hash)] pub struct Loc { file: String, line: usize, @@ -64,6 +64,12 @@ impl Default for Loc { } } +impl PartialEq for Loc { + fn eq(&self, _: &Self) -> bool { + true // ignore eq cause comparing 2 locations is irrelevant + } +} + pub trait LocIncr { fn inc_line(&mut self); fn inc_col(&mut self); diff --git a/src/parser/ast/literal.rs b/src/parser/ast/literal.rs index 4daaf1d..9d279dd 100644 --- a/src/parser/ast/literal.rs +++ b/src/parser/ast/literal.rs @@ -1,5 +1,5 @@ -use crate::{common::{Loc, loc::LocBox}, parser::ast::{Program, typ::Type}, tokeniser::tokentype::*, validator::{predefined::SIZE, validate_expr}}; +use crate::{common::{Loc, loc::LocBox}, debug, parser::ast::{Program, typ::Type}, tokeniser::tokentype::*, validator::{predefined::SIZE, validate_expr}}; use super::expr::Expr; @@ -26,7 +26,10 @@ impl Literal { let t = match self { Self::Number(_) => Type::Builtin { name: String::from("usize"), size: SIZE as u8, signed: false }, Self::Ident(ident) => Type::Owned(ident.clone()), - Self::String(str) if str.cstr => Type::Ref { inner: Box::new(Type::Owned(Ident(String::from("cstr")))), mutable: false}, + Self::String(str) if str.cstr => { + debug!("is cstr"); + Type::Ref { inner: Box::new(Type::Owned(Ident(String::from("cstr")))), mutable: false} + }, Self::String(str) if !str.cstr => Type::Ref { inner: Box::new(Type::Owned(Ident(String::from("str")))), mutable: false}, Self::String(_) => unreachable!("stupid rust"), Self::Char(_) => Type::Owned(Ident(String::from("char"))), diff --git a/src/parser/ast/statement.rs b/src/parser/ast/statement.rs index c2ee1fa..9969c2e 100644 --- a/src/parser/ast/statement.rs +++ b/src/parser/ast/statement.rs @@ -60,17 +60,32 @@ pub struct Enum { pub fields: Vec, } -#[derive(Debug, Clone, PartialEq, PartialOrd, Hash)] +#[derive(Debug, Clone, PartialOrd, Hash)] pub struct Function { pub struct_name: Option, - pub name: Ident, + pub name: Option, pub params: Vec<(Ident, LocBox)>, - pub ret_type: Option>, + pub ret_type: Option>>, pub qual_const: bool, pub qual_extern: Option, // abi pub body: Option, // If None then its a type declaration } +impl PartialEq for Function { + fn eq(&self, other: &Self) -> bool { + dbg!(self.params == other.params); + dbg!(self.ret_type == other.ret_type); + dbg!(self.qual_extern == other.qual_extern); + dbg!(self.qual_const == other.qual_const); + dbg!(&self.params); + dbg!(&self.ret_type); + self.params == other.params && + self.ret_type == other.ret_type && + self.qual_extern == other.qual_extern && + self.qual_const == other.qual_const + } +} + impl Display for Function { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut extrn = String::new(); @@ -99,17 +114,25 @@ impl Display for Function { impl Function { pub fn get_full_name(&self) -> String { - if let Some(sn) = &self.struct_name { - format!("{sn}__S__{}", self.name.0) + if let Some(name) = &self.name { + if let Some(sn) = &self.struct_name { + format!("{sn}__S__{}", name.0) + } else { + format!("{}", name.0) + } } else { - format!("{}", self.name.0) + String::new() } } pub fn get_full_name_pretty(&self) -> String { - if let Some(sn) = &self.struct_name { - format!("{sn}::{}", self.name.0) + if let Some(name) = &self.name { + if let Some(sn) = &self.struct_name { + format!("{sn}::{}", name.0) + } else { + format!("{}", name.0) + } } else { - format!("{}", self.name.0) + String::new() } } pub fn get_def_as_str(&self) -> String { diff --git a/src/parser/ast/typ.rs b/src/parser/ast/typ.rs index 2633b48..435c19e 100644 --- a/src/parser/ast/typ.rs +++ b/src/parser/ast/typ.rs @@ -2,7 +2,7 @@ use std::{clone, collections::HashSet, fmt::Display}; use anyhow::bail; -use crate::{common::loc::LocBox, error, info, validator::predefined::{BuiltinType, get_builtin_from_name}}; +use crate::{common::loc::LocBox, error, info, parser::ast::statement::Function, validator::predefined::{BuiltinType, get_builtin_from_name}}; use super::{expr::Expr, literal::Literal, Ident, Program}; @@ -24,7 +24,8 @@ pub enum Type { name: String, size: u8, signed: bool, - } + }, + FnPtr(Function) } impl Type { @@ -67,6 +68,7 @@ impl Type { _ => true, } }, + Self::FnPtr(_) | Self::Owned(_) | Self::SizedArray { .. } | Self::Builtin { .. } | @@ -100,6 +102,7 @@ impl Type { Type::UnsizedArray { inner } => { f(inner, program, used_types) } + Type::FnPtr(_) | Type::Builtin { .. } => Ok(slf.clone()), } } @@ -129,6 +132,7 @@ impl Type { bail!("owo? missing value: {ident}"); } } + Self::FnPtr(_) | Self::SizedArray { .. } | Self::Builtin { .. } | Self::UnsizedArray { .. } => Ok(self.clone()), @@ -155,6 +159,7 @@ impl Type { Self::Ref { inner, .. } | Self::SizedArray { inner, .. } | Self::UnsizedArray { inner, .. } => inner.convert_owned_to_real_type(program), + Self::FnPtr(_) | Self::Builtin { .. } => (), } } @@ -174,6 +179,9 @@ impl Type { } else if let Some(var) = program.get_var(ident) { Ok(var.1.inner().typ.clone().expect("type should be computed if were already using it").inner().clone()) + } else + if let Some(func) = program.functions.get(ident) { + Ok(Type::FnPtr(func.inner().clone())) } else { bail!("owo? missing value: {ident}"); } @@ -181,6 +189,7 @@ impl Type { Self::Ref { .. } | Self::SizedArray { .. } | Self::Builtin { .. } | + Self::FnPtr(_) | Self::UnsizedArray { .. } => Ok(self.clone()), } @@ -197,6 +206,7 @@ impl Type { } }, Self::SizedArray { .. } => false, + Self::FnPtr(_) | Self::UnsizedArray { .. } => false, Self::Builtin { name, .. } => { match name.as_str() { @@ -225,6 +235,7 @@ impl Type { _ => None } }, + Self::FnPtr(_) | Self::SizedArray { .. } => None, Self::UnsizedArray { .. } => None, Self::Builtin { name, .. } => { @@ -273,6 +284,7 @@ impl Type { pub fn size_of(&self, program: &Program) -> anyhow::Result { fn f(t: &Type, program: &Program, behind_a_ptr: bool) -> anyhow::Result { match t { + Type::FnPtr(_) | Type::Ref { .. } => { // TODO: Use the actual ptr size Ok(size_of::<*const ()>()) @@ -323,6 +335,9 @@ impl Type { impl Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + Self::FnPtr(func) => { + write!(f, "{func}") + } Self::Ref { inner, mutable } => { if *mutable { write!(f, "&mut {inner}") diff --git a/src/parser/expr.rs b/src/parser/expr.rs index 360e75f..50c9dd1 100644 --- a/src/parser/expr.rs +++ b/src/parser/expr.rs @@ -31,6 +31,7 @@ const BINOP_LIST: &[TokenType] = &[ TokenType::Punct(Punctuation::XorEq), TokenType::Punct(Punctuation::Eq), TokenType::Punct(Punctuation::EqEq), + TokenType::Punct(Punctuation::Neq), TokenType::Punct(Punctuation::Lt), TokenType::Punct(Punctuation::Gt), TokenType::Punct(Punctuation::Le), @@ -45,6 +46,7 @@ pub fn parse_expr(tokens: &mut Vec, precedence: usize, consume_semi: bool Some(LocBox::new(kw.loc(), Expr::Self_ { strct: None })) } else if let Some(_) = utils::check(tokens, TokenType::ident("")) { + debug!("is ident"); let p = parse_path(tokens)?; if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyL)) { Some(parse_struct_literal(tokens, p.inner().unwrap_path(), cli, prog)?) @@ -481,7 +483,7 @@ fn parse_binop(tokens: &mut Vec, mut lhs: LocBox, precedence: usize loop { let op_loc; - let op = match tokens.last() { + let mut op = match tokens.last() { Some(op) if BINOP_LIST.contains(&op.tt()) => { op_loc = op.loc().clone(); let TokenType::Punct(op) = op.tt() else {unreachable!()}; @@ -500,13 +502,28 @@ fn parse_binop(tokens: &mut Vec, mut lhs: LocBox, precedence: usize Some(_) | None => break, }; + + _ = tokens.pop(); + + // Fix for parsing multiple refs in types and references being parsed as && (logical and) + if op == Punctuation::Ampersand { + if let Some(tok) = tokens.last() { + match tok.tt() { + TokenType::Punct(Punctuation::Ampersand) => { + _ = tokens.pop(); + op = Punctuation::AndAnd; + } + _ => () + } + } + } + debug!("OP: {op:?}"); let (lp, rp) = op.precedence().unwrap(); if lp < precedence { break } - _ = tokens.pop(); let Some(rhs) = parse_expr(tokens, rp, false, cli, prog)? else {break;}; lhs = LocBox::new(&op_loc, Expr::BinOp { typ: op, diff --git a/src/parser/stat.rs b/src/parser/stat.rs index 9aca6a5..d5c8147 100644 --- a/src/parser/stat.rs +++ b/src/parser/stat.rs @@ -17,7 +17,7 @@ use super::ast::statement::{ConstVar, Enum, Function, Statement, StaticVar, Stru type Result = anyhow::Result; pub fn parse_statement(tokens: &mut Vec, cli: &CliArgs, prog: &mut Program) -> Result>> { - if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Fn)) { + if let Some(_) = utils::check_from_many(tokens, &[TokenType::Keyword(Keyword::Fn), TokenType::Keyword(Keyword::Extern)]) { Ok(Some(parse_fn(tokens, cli, prog)?)) } else if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Type)) { @@ -192,6 +192,17 @@ pub fn parse_type_alias(tokens: &mut Vec) -> Result> { pub fn parse_fn(tokens: &mut Vec, cli: &CliArgs, prog: &mut Program) -> Result> { error!("fnc"); + let mut qual_extern = None; + if let Some(_) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Extern)) { + if let Some(tok) = utils::check_consume(tokens, TokenType::string("", false)) { + if let TokenType::String(str) = tok.tt() { + qual_extern = Some(str.clone()); + } + } else { + qual_extern = Some(TString::default()); + } + } + // Just remove the kw since we checked it before let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Fn), "")?; let mut struct_name = None; @@ -206,7 +217,7 @@ pub fn parse_fn(tokens: &mut Vec, cli: &CliArgs, prog: &mut Program) -> R // Check for return type cause it optional let mut ret_type = None; if let Some(_) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Arrow)) { - ret_type = Some(parse_type(tokens)?); + ret_type = Some(Box::new(parse_type(tokens)?)); } let body; if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyL)) { @@ -228,11 +239,11 @@ pub fn parse_fn(tokens: &mut Vec, cli: &CliArgs, prog: &mut Program) -> R params.append(&mut params_partial.1); Ok(LocBox::new(kw.loc(), Statement::Fn(Function{ struct_name, - name, + name: Some(name), params, ret_type, qual_const: false, - qual_extern: None, + qual_extern, body, }))) } diff --git a/src/parser/typ.rs b/src/parser/typ.rs index bcf50e0..f50e3e5 100644 --- a/src/parser/typ.rs +++ b/src/parser/typ.rs @@ -1,6 +1,6 @@ use anyhow::{Result, bail}; -use crate::{cli::CliArgs, common::loc::LocBox, lerror, parser::{Delimiter, ast::{Ident, Program, expr::Expr, literal::Literal}}, tokeniser::Token, validator::predefined::get_builtin_from_name}; +use crate::{cli::CliArgs, common::loc::LocBox, lerror, parser::{Delimiter, ast::{Ident, Program, expr::Expr, literal::Literal, statement::{Function, Statement}}, stat::parse_fn_params}, tokeniser::Token, validator::predefined::get_builtin_from_name}; use super::{ast::{typ::Type, TokenType}, expr::parse_expr, utils, Keyword, Punctuation}; @@ -19,6 +19,11 @@ pub fn parse_type(tokens: &mut Vec) -> Result> { } let mut typ; + if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Fn)) { + let decl = parse_fn(tokens)?; + loc = Some(decl.loc().clone()); + typ = Type::FnPtr(decl.inner().clone()); + } else if let Some(start) = utils::check_consume(tokens, TokenType::Delim(super::Delimiter::SquareL)) { if let None = loc { loc = Some(start.loc().clone()); @@ -75,3 +80,32 @@ pub fn parse_type(tokens: &mut Vec) -> Result> { } Ok(LocBox::new(&loc.unwrap(), typ)) } + +pub fn parse_fn(tokens: &mut Vec) -> Result> { + let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Fn), "")?; + +// disable member functions for types (for now) +// let mut struct_name = None; +// let mut name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident(); + // Check if this is a struct method +// if let Some(_) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Fieldaccess)) { +// struct_name = Some(name); +// name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident(); +// } + let params = parse_fn_params(tokens)?; + + // Check for return type cause it optional + let mut ret_type = None; + if let Some(_) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Arrow)) { + ret_type = Some(Box::new(parse_type(tokens)?)); + } + Ok(LocBox::new(kw.loc(),Function{ + struct_name: None, + name: None, + params: params.1, + ret_type, + qual_const: false, + qual_extern: None, + body: None, + })) +} diff --git a/src/targets/mod.rs b/src/targets/mod.rs index 2de5425..b2bc42f 100644 --- a/src/targets/mod.rs +++ b/src/targets/mod.rs @@ -56,7 +56,10 @@ pub fn compile(cli: &CliArgs, programs: Vec<(PathBuf, Program)>) -> anyhow::Resu objs.push(obj_p); } let out = Path::new(&cli.output); - target.link(objs, &out, &cli.linker_args)?; + + let mut args = Vec::new(); + args.append(&mut cli.linker_args.clone()); + target.link(objs, &out, &args)?; Ok(()) } diff --git a/src/targets/x86_64/asmgen/linux/mod.rs b/src/targets/x86_64/asmgen/linux/mod.rs index 4c3a1d9..1156748 100644 --- a/src/targets/x86_64/asmgen/linux/mod.rs +++ b/src/targets/x86_64/asmgen/linux/mod.rs @@ -165,12 +165,15 @@ impl FunctionCtx { impl AsmGen { pub fn write_func(&self, program: &Program, f: &mut File, func: Function, loc: Loc) -> anyhow::Result<()> { - if let Some(body) = &func.body { + if func.qual_extern.is_some() { + return Ok(()); + } + if let Some(body) = &func.body && let Some(name) = &func.name { let mut fc = FunctionCtx::new(); let name = if let Some(struct_name) = &func.struct_name { - format!("{}${}", struct_name, func.name) + format!("{}${}", struct_name, name) } else { - func.name.to_string() + name.to_string() }; info!("writing norm function: {name}"); writeln!(f, "{}: ; {} {}", name, loc, func.get_full_name_pretty())?; @@ -217,8 +220,8 @@ impl AsmGen { writeln!(f, " ret")?; } } - } else { - info!("writing function stub: {}", func.name); + } else if let Some(_) = &func.name { + info!("writing function stub: {}", func.get_full_name_pretty()); writeln!(f, " ret")?; } writeln!(f, "\n")?; @@ -601,6 +604,7 @@ impl AsmGen { writeln!(f, "mov [rbx+{offset}], rax")?; }, Punctuation::EqEq => {}, + Punctuation::Neq => {}, Punctuation::Lt => {}, Punctuation::Gt => {}, Punctuation::Le => {}, @@ -624,6 +628,8 @@ impl AsmGen { } } else if let Some(_) = program.get_const_var(&ident) { writeln!(f, " lea rax, [rel {ident}] ; const {ident}")?; + } else if let Some(_) = program.functions.get(&ident) { + writeln!(f, " lea rax, [rel {ident}] ; fn ptr {ident}")?; } else { panic!() } diff --git a/src/tokeniser/mod.rs b/src/tokeniser/mod.rs index 5d799cd..5050af9 100644 --- a/src/tokeniser/mod.rs +++ b/src/tokeniser/mod.rs @@ -282,7 +282,6 @@ lazy_static::lazy_static!( ("%", TokenType::Punct(Punctuation::Mod)), ("<<", TokenType::Punct(Punctuation::Shl)), (">>", TokenType::Punct(Punctuation::Shr)), - ("&&", TokenType::Punct(Punctuation::AndAnd)), ("||", TokenType::Punct(Punctuation::OrOr)), ("|", TokenType::Punct(Punctuation::Or)), (">", TokenType::Punct(Punctuation::Gt)), diff --git a/src/validator/mod.rs b/src/validator/mod.rs index cf7f6f5..1b33b44 100644 --- a/src/validator/mod.rs +++ b/src/validator/mod.rs @@ -423,6 +423,7 @@ pub fn validate_expr(prog: &mut Program, expr: &mut LocBox) -> anyhow::Res *signed = var_t.is_signed(prog).expect("verified as numeric"); Ok(None) } + Punctuation::Neq | Punctuation::Eq => { let var = validate_expr(prog, left)?.unwrap(); let var_t = var.get_absolute_value(prog)?; @@ -435,7 +436,7 @@ pub fn validate_expr(prog: &mut Program, expr: &mut LocBox) -> anyhow::Res Ok(None) } - _ => unreachable!() + v => unreachable!("{v:?}") } }, Expr::ArrayIndex { name, index } => { @@ -473,6 +474,7 @@ pub fn validate_expr(prog: &mut Program, expr: &mut LocBox) -> anyhow::Res } } Type::Ref { .. } | + Type::FnPtr(_) | Type::Builtin { .. } => { lerror!(loc, "Numeric, pointer, and void types are not indexable (TODO: Maybe allow indexing pointers?)"); bail!("") @@ -489,6 +491,7 @@ pub fn validate_expr(prog: &mut Program, expr: &mut LocBox) -> anyhow::Res }; let mut left = left.unwrap(); left.convert_owned_to_real_type(prog); + dbg!(&prog.curr_fn_args); *l_typ = Some(Box::new(left.clone())); match left { Type::Ref { inner, mutable: _ } => { @@ -510,7 +513,7 @@ pub fn validate_expr(prog: &mut Program, expr: &mut LocBox) -> anyhow::Res v => panic!("{v:?}"), } } - v => panic!("{v:?}"), + v => panic!("{} {v:?}", expr.loc()), } Ok(None) @@ -564,9 +567,10 @@ pub fn validate_expr(prog: &mut Program, expr: &mut LocBox) -> anyhow::Res fn validate_fn(prog: &mut Program, func: &mut Function) -> anyhow::Result<()> { prog.scope = Some(Scope::default()); prog.curr_struct = func.struct_name.clone(); - + dbg!(&func.params); for param in &func.params { let t = validate_type(prog, ¶m.1)?; + dbg!(&t); prog.curr_fn_args.insert(param.0.clone(), LocBox::new(&Loc::default(), t.clone())); } if let Some(body) = &mut func.body { @@ -620,16 +624,16 @@ fn check_that_types_exist_for_items(prog: &mut Program, items: &Vec) -> any for (name, t) in &func.params { if let Err(_) = validate_type(prog, t) { if let Some(sn) = &func.struct_name { - lerror!(t.loc(), "Type '{}', of argument, '{name}' in function '{}::{}' does not exist", t.inner(), sn, func.name); + lerror!(t.loc(), "Type '{}', of argument, '{name}' in function '{}::{}' does not exist", t.inner(), sn, func.get_full_name_pretty()); } else { - lerror!(t.loc(), "Type '{}', of argument, '{name}' in function '{}' does not exist", t.inner(), func.name); + lerror!(t.loc(), "Type '{}', of argument, '{name}' in function '{}' does not exist", t.inner(), func.get_full_name_pretty()); } errored = true; } } if let Some(ret_typ) = &func.ret_type { if let Err(_) = validate_type(prog, &ret_typ) { - lerror!(ret_typ.loc(), "Return type '{}' of function '{}' does not exist", ret_typ.inner(), func.name); + lerror!(ret_typ.loc(), "Return type '{}' of function '{}' does not exist", ret_typ.inner(), func.get_full_name_pretty()); errored = true; } } @@ -674,6 +678,7 @@ pub fn validate_type(prog: &mut Program, typ: &LocBox) -> anyhow::Result Ok(typ.clone()), Type::Owned(ident) => { if let Some(builtin) = get_builtin_from_name(&ident.0) { @@ -691,7 +696,7 @@ pub fn validate_type(prog: &mut Program, typ: &LocBox) -> anyhow::Result Ok(typ.clone()) } } - f(prog, &typ.inner().get_real_value_of_alias(&Ident::new(""), prog)?, typ.loc()) + f(prog, &typ.inner(), typ.loc()) } @@ -703,16 +708,18 @@ fn collect_types_and_constants(prog: &mut Program, items: &mut Vec) { let loc = stat.loc().clone(); match stat.inner_mut() { Statement::Fn(func)=> { - if let Some(struct_name) = &func.struct_name { - if let Some(v) = prog.member_functions.get_mut(&struct_name) { - v.insert(func.name.clone(), LocBox::new(&loc, func.clone())); - } else { - let mut v = HashMap::new(); - v.insert(func.name.clone(), LocBox::new(&loc, func.clone())); - prog.member_functions.insert(struct_name.clone(), v); + if let Some(name) = &func.name { + if let Some(struct_name) = &func.struct_name { + if let Some(v) = prog.member_functions.get_mut(&struct_name) { + v.insert(name.clone(), LocBox::new(&loc, func.clone())); + } else { + let mut v = HashMap::new(); + v.insert(name.clone(), LocBox::new(&loc, func.clone())); + prog.member_functions.insert(struct_name.clone(), v); + } + } else { + prog.functions.insert(name.clone(), LocBox::new(&loc, func.clone())); } - } else { - prog.functions.insert(func.name.clone(), LocBox::new(&loc, func.clone())); } } Statement::Enum(enm) => { diff --git a/src/validator/predefined.rs b/src/validator/predefined.rs index d5728dc..3daea28 100644 --- a/src/validator/predefined.rs +++ b/src/validator/predefined.rs @@ -143,7 +143,7 @@ pub fn load_builtin(prog: &mut Program) { let mut ret_type = None; if !ret_typ.is_void() { - ret_type = Some(LocBox::new(&Loc::default(), ret_typ.clone())); + ret_type = Some(Box::new(LocBox::new(&Loc::default(), ret_typ.clone()))); } for (name, typ) in args { params.push((Ident(name.to_string()), LocBox::new(&Loc::new("(internal)", 0, 0), typ.clone()))); @@ -151,7 +151,7 @@ pub fn load_builtin(prog: &mut Program) { let f = Function { struct_name: None, - name: Ident(name.to_string()), + name: Some(Ident(name.to_string())), params, ret_type, qual_const: false, diff --git a/std/lib/beaker.mcl b/std/lib/beaker.mcl index 7ccf69b..426a9bf 100644 --- a/std/lib/beaker.mcl +++ b/std/lib/beaker.mcl @@ -1,4 +1,4 @@ - +include "std/core.mcl"; const MAX_CONTEXT_VARS: usize = 32; const MAX_KEY_LEN: usize = 64; @@ -23,73 +23,73 @@ enum ContextType { type ContextType = i32; struct CV_array_data { values: &&char, - count: i32, + count: i32 } struct CV_2d_array_data { values: &&&char, - count: i32, + count: i32 } struct ContextVarStr { - key: char[MAX_KEY_LEN], + key: [char; MAX_KEY_LEN], typ: ContextType, - value: char[MAX_VALUE_LEN] + value: [char; MAX_VALUE_LEN] } struct ContextVarArr { - key: char[MAX_KEY_LEN], + key: [char; MAX_KEY_LEN], typ: ContextType, value: CV_array_data, } struct ContextVar2dArr { - key: char[MAX_KEY_LEN], + key: [char; MAX_KEY_LEN], typ: ContextType, value: CV_2d_array_data, } struct ContextVar { - key: char[MAX_KEY_LEN], + key: [char; MAX_KEY_LEN], typ: ContextType, - value: char[MAX_VALUE_LEN] + value: [char; MAX_VALUE_LEN] } struct TemplateContext { - vars: ContextVar[MAX_CONTEXT_VARS], + vars: [ContextVar; MAX_CONTEXT_VARS], count: i32, } struct UrlParam { - key: char[MAX_KEY_LEN], - value: char[MAX_VALUE_LEN], + key: [char; MAX_KEY_LEN], + value: [char; MAX_VALUE_LEN], } struct UrlParams { - params: UrlParam[MAX_URL_PARAMS], + params: [UrlParam; MAX_URL_PARAMS], count: i32 } struct Cookie { - name: char[MAX_KEY_LEN], - value: char[MAX_VALUE_LEN], - expires: char[MAX_VALUE_LEN], - path: char[MAX_KEY_LEN], + name: [char; MAX_KEY_LEN], + value: [char; MAX_VALUE_LEN], + expires: [char; MAX_VALUE_LEN], + path: [char; MAX_KEY_LEN], http_only: bool, secure: bool } -type RequestHandler = fn(params: &UrlParams); +type RequestHandler = fn(params: &UrlParams) -> i32; struct RouteHandler { - path: char[MAX_PATH_LEN], + path: [char; MAX_PATH_LEN], handler: RequestHandler } extern fn new_context() -> TemplateContext; extern fn context_set(ctx: &mut TemplateContext, key: &cstr, value: &cstr); extern fn context_set_string_array(ctx: &mut TemplateContext, key: &cstr, values: &cstr, count: i32); -extern fn context_set_array_of_arrays(ctx: &mut TemplateContext, key: &cstr, values: &cstr[][], outer_count: i32, inner_count: i32); +extern fn context_set_array_of_arrays(ctx: &mut TemplateContext, key: &cstr, values: [[&cstr]], outer_count: i32, inner_count: i32); extern fn free_context(ctx: &mut TemplateContext); extern fn render_template(template_file: &cstr, ctx: &mut TemplateContext) -> &cstr; diff --git a/test2 b/test2 new file mode 100755 index 0000000..664becc Binary files /dev/null and b/test2 differ diff --git a/test2.mcl b/test2.mcl index b01f40e..55cdf2b 100644 --- a/test2.mcl +++ b/test2.mcl @@ -1,6 +1,18 @@ // include "std/core.mcl"; -include "beaker.mcl"; +include "std/lib/beaker.mcl"; + + + +fn hello_world_handler(params: &UrlParams) -> i32 { + send_response(c"Hello, World!"); + return 0; +} fn main() -> i32 { - //puts("owo\n"); + set_handler(c"/", hello_world_handler); + let result = beaker_run(c"127.0.0.1", 0xff00000000000000 as i32); + + if (!(result as bool)) { + eputs("[APP] Error: Beaker server failed to start.\n"); + } }