Fix bunch of bugs, endianess of numbers seems to befucked, i have no idea why
This commit is contained in:
BIN
libbeaker.so
Executable file
BIN
libbeaker.so
Executable file
Binary file not shown.
@@ -22,6 +22,10 @@ pub struct CliArgs {
|
||||
/// Linker args
|
||||
#[arg(long, short='L')]
|
||||
pub linker_args: Vec<String>,
|
||||
|
||||
/// Link with C libs, required for any C libraries
|
||||
#[arg(long, short='C')]
|
||||
pub link_c: bool,
|
||||
|
||||
/// All input files
|
||||
#[clap(num_args = 1..)]
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"))),
|
||||
|
||||
@@ -60,17 +60,32 @@ pub struct Enum {
|
||||
pub fields: Vec<Ident>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Hash)]
|
||||
#[derive(Debug, Clone, PartialOrd, Hash)]
|
||||
pub struct Function {
|
||||
pub struct_name: Option<Ident>,
|
||||
pub name: Ident,
|
||||
pub name: Option<Ident>,
|
||||
pub params: Vec<(Ident, LocBox<Type>)>,
|
||||
pub ret_type: Option<LocBox<Type>>,
|
||||
pub ret_type: Option<Box<LocBox<Type>>>,
|
||||
pub qual_const: bool,
|
||||
pub qual_extern: Option<TString>, // abi
|
||||
pub body: Option<Block>, // 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 {
|
||||
|
||||
@@ -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<usize> {
|
||||
fn f(t: &Type, program: &Program, behind_a_ptr: bool) -> anyhow::Result<usize> {
|
||||
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}")
|
||||
|
||||
@@ -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<Token>, 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<Token>, mut lhs: LocBox<Expr>, 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<Token>, mut lhs: LocBox<Expr>, 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,
|
||||
|
||||
@@ -17,7 +17,7 @@ use super::ast::statement::{ConstVar, Enum, Function, Statement, StaticVar, Stru
|
||||
type Result<T> = anyhow::Result<T>;
|
||||
|
||||
pub fn parse_statement(tokens: &mut Vec<Token>, cli: &CliArgs, prog: &mut Program) -> Result<Option<LocBox<Statement>>> {
|
||||
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<Token>) -> Result<LocBox<Statement>> {
|
||||
|
||||
pub fn parse_fn(tokens: &mut Vec<Token>, cli: &CliArgs, prog: &mut Program) -> Result<LocBox<Statement>> {
|
||||
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<Token>, 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<Token>, 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,
|
||||
})))
|
||||
}
|
||||
|
||||
@@ -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<Token>) -> Result<LocBox<Type>> {
|
||||
}
|
||||
|
||||
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<Token>) -> Result<LocBox<Type>> {
|
||||
}
|
||||
Ok(LocBox::new(&loc.unwrap(), typ))
|
||||
}
|
||||
|
||||
pub fn parse_fn(tokens: &mut Vec<Token>) -> Result<LocBox<Function>> {
|
||||
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,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
|
||||
@@ -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!()
|
||||
}
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -423,6 +423,7 @@ pub fn validate_expr(prog: &mut Program, expr: &mut LocBox<Expr>) -> 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<Expr>) -> 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<Expr>) -> 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<Expr>) -> 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<Expr>) -> 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<Expr>) -> 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<Ast>) -> 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<Type>) -> anyhow::Result<T
|
||||
match typ {
|
||||
Type::SizedArray { .. } |
|
||||
Type::UnsizedArray { .. } |
|
||||
Type::FnPtr(_) |
|
||||
Type::Ref { .. } => 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<Type>) -> anyhow::Result<T
|
||||
Type::Builtin { .. } => 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<Ast>) {
|
||||
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) => {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
16
test2.mcl
16
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");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user