Fix bunch of bugs, endianess of numbers seems to befucked, i have no idea why

This commit is contained in:
2026-02-12 23:26:59 +02:00
parent 96f8aa3bbb
commit dd1b6af259
17 changed files with 208 additions and 68 deletions

BIN
libbeaker.so Executable file

Binary file not shown.

View File

@@ -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..)]

View File

@@ -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);

View File

@@ -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"))),

View File

@@ -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 {

View File

@@ -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}")

View File

@@ -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,

View File

@@ -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,
})))
}

View File

@@ -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,
}))
}

View File

@@ -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(())
}

View File

@@ -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!()
}

View File

@@ -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)),

View File

@@ -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, &param.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) => {

View File

@@ -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,

View File

@@ -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;

BIN
test2 Executable file

Binary file not shown.

View File

@@ -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");
}
}