Add external functions (both import and export), make includes work
still need to fix literal arrays, it has the same problem as struct literals had with moving the literal into memory and modifying the memory with variables
This commit is contained in:
parent
834b5b1213
commit
081ff9a27a
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,4 +1,6 @@
|
|||
/target
|
||||
/*.c
|
||||
/*.s
|
||||
/*.o
|
||||
/*.ssa
|
||||
/test
|
||||
|
|
|
|||
55
editor_support/mclang4.vim
Normal file
55
editor_support/mclang4.vim
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
" Vim syntax file
|
||||
" Language: MClang4
|
||||
" Maintainer: MCorange
|
||||
" Maintainer: xomf
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
syn match MCLangSlash '/' containedin=ALLBUT,MCLangComment
|
||||
syn match MCLangComment '//.*'
|
||||
|
||||
syn region MCLangComment start='/\*' end='\*/' contains=@Spell
|
||||
|
||||
syn keyword MCLangKeywords fn if else struct enum type while for break continue let const mut static include extern return loop as
|
||||
" syn keyword MCLangOp + -
|
||||
syn keyword MCLangTypes void u8 u16 u32 u64 i8 i16 i32 i64 usize isize str
|
||||
syn keyword MCLangBool true false
|
||||
syn keyword MCLangConst NULL
|
||||
" i8 i16 i32 i64 f32 f64
|
||||
syn region MCLangString start=+"+ skip=+\\.+ end=+"+ contains=@Spell
|
||||
syn region MCLangChar start=+'+ skip=+\\.+ end=+'+
|
||||
|
||||
syn match MCLangFuncCall '\<[A-Za-z_][A-Za-z0-9_]*\>\ze\s*(' containedin=ALLBUT,MCLangString,MCLangChar,MCLangComment
|
||||
syn match MCLangFuncCall '\<[A-Za-z_][A-Za-z0-9_]*::[A-Za-z_][A-Za-z0-9_]*\>\ze\s*(' containedin=ALLBUT,MCLangString,MCLangChar,MCLangComment
|
||||
"syn match MCLangFuncDef '\<fn\s\+\zs[A-Za-z_][A-Za-z0-9_]*\.\?\>' containedin=ALLBUT,MCLangString,MCLangChar,MCLangComment
|
||||
"syn match MCLangConstName '\<const\s\+\zs[A-Za-z_][A-Za-z0-9_]*\>' containedin=ALLBUT,MCLangString,MCLangChar,MCLangComment
|
||||
syn match MCLangIdentifier '\<[A-Za-z_][A-Za-z0-9_]*\>'
|
||||
syn match MCLangOp '[+\-*%&|^!~<>]=\?\|==\|!=\|<=\|>=\|&&\|\\|\|::\|:\|[;,\.]' containedin=ALLBUT,MCLangString,MCLangChar,MCLangComment
|
||||
syn match MCLangNumber '\<\(0b[01]\+\|0x[0-9A-Fa-f]\+\|\d\+\.\d*\|\.\d\+\|\d\+\)\>' containedin=ALLBUT,MCLangString,MCLangChar,MCLangComment
|
||||
|
||||
|
||||
|
||||
syn match MCLangDelim /[()]/
|
||||
syn match MCLangDelim /[{}]/
|
||||
syn match MCLangDelim /[\[\]]/
|
||||
|
||||
let b:current_syntax = "MCLang4"
|
||||
|
||||
hi def link MCLangComment Comment
|
||||
hi def link MCLangTypes Type
|
||||
hi def link MCLangString String
|
||||
hi def link MCLangChar Character
|
||||
hi def link MCLangNumber Constant
|
||||
hi def link MCLangConst Constant
|
||||
"hi def link MCLangConstName Constant
|
||||
hi def link MCLangBool Boolean
|
||||
hi def link MCLangDelim Delimiter
|
||||
hi def link MCLangOp Operator
|
||||
hi def link MCLangKeywords Keyword
|
||||
"hi def link MCLangIdentifier Identifier
|
||||
hi def link MCLangFuncCall Function
|
||||
"hi def link MCLangFuncDef Function
|
||||
|
||||
|
||||
|
||||
7
include/std.mcl
Normal file
7
include/std.mcl
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
|
||||
// fn syscall(arg_count: usize, syscall_num: usize, args: )
|
||||
|
||||
fn puts(s: &str) {
|
||||
__INTERNAL_syscall(1 as u8, 1 as u8, &[s] as &[&void]);
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ use clap::{error::ErrorKind, CommandFactory};
|
|||
use crate::logger::Level;
|
||||
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
#[derive(Debug, Default, clap::Parser)]
|
||||
pub struct CliArgs {
|
||||
/// Output more info, will get overwritten if -q|--quiet is specified
|
||||
#[arg(long, short)]
|
||||
|
|
@ -13,6 +13,8 @@ pub struct CliArgs {
|
|||
quiet: bool,
|
||||
#[arg(long, short, value_parser=crate::targets::get_all_targets(), default_value_t=crate::targets::get_default_target())]
|
||||
pub target: String,
|
||||
#[arg(long="include", short='I', default_values=["include"])]
|
||||
pub include_paths: Vec<String>,
|
||||
/// Output file
|
||||
#[arg(long, short, default_value="a.out")]
|
||||
pub output: String,
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@ fn main() -> anyhow::Result<()> {
|
|||
let data = std::fs::read_to_string(&fp).unwrap();
|
||||
info!("Tokenising {file}");
|
||||
let tokens = mclangc::tokeniser::tokenise(&data, &file)?;
|
||||
// dbg!(&tokens);
|
||||
info!("Parsing {file}");
|
||||
let mut prog = mclangc::parser::parse_program(tokens)?;
|
||||
let mut prog = mclangc::parser::parse_program(tokens, &cli)?;
|
||||
// dbg!(&prog.ast);
|
||||
info!("Validating {file}");
|
||||
mclangc::validator::validate_code(&mut prog)?;
|
||||
// dbg!(&prog.literals);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ pub enum Statement {
|
|||
Enum(Enum),
|
||||
ConstVar(ConstVar),
|
||||
StaticVar(StaticVar),
|
||||
Include,
|
||||
Let(Let),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashMap};
|
|||
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
use crate::{common::loc::LocBox, debug, lerror, parser::{Punctuation, ast::expr::StructLit, typ::parse_type}, tokeniser::Token};
|
||||
use crate::{cli::CliArgs, common::loc::LocBox, debug, lerror, parser::{Punctuation, ast::expr::StructLit, typ::parse_type}, tokeniser::Token};
|
||||
|
||||
use super::{ast::{expr::{Block, CallParams, Expr, IfBranchExpr, IfExpr, Path}, literal::Literal, TokenType}, parse_item, utils, Delimiter, Keyword};
|
||||
|
||||
|
|
@ -37,14 +37,14 @@ const BINOP_LIST: &[TokenType] = &[
|
|||
TokenType::Punct(Punctuation::Ge),
|
||||
];
|
||||
|
||||
pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool) -> Result<Option<LocBox<Expr>>> {
|
||||
pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool, cli: &CliArgs) -> Result<Option<LocBox<Expr>>> {
|
||||
let res = if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::ParenL)) {
|
||||
Some(parse_group(tokens)?)
|
||||
Some(parse_group(tokens, cli)?)
|
||||
} else
|
||||
if let Some(_) = utils::check(tokens, TokenType::ident("")) {
|
||||
let p = parse_path(tokens)?;
|
||||
if let Some(t) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyL)) {
|
||||
Some(parse_struct_literal(tokens, p.inner().unwrap_path())?)
|
||||
Some(parse_struct_literal(tokens, p.inner().unwrap_path(), cli)?)
|
||||
} else {
|
||||
Some(p)
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool
|
|||
TokenType::Punct(Punctuation::Ampersand),
|
||||
TokenType::Punct(Punctuation::Star),
|
||||
]) {
|
||||
Some(parse_unop(tokens)?)
|
||||
Some(parse_unop(tokens, cli)?)
|
||||
} else
|
||||
if let Some(_) = utils::check_from_many(tokens, &[
|
||||
TokenType::string("", false),
|
||||
|
|
@ -66,15 +66,15 @@ pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool
|
|||
TokenType::Keyword(Keyword::True),
|
||||
TokenType::Keyword(Keyword::False)
|
||||
]) {
|
||||
Some(parse_literal(tokens)?)
|
||||
Some(parse_literal(tokens, cli)?)
|
||||
} else if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::While)) {
|
||||
return Ok(Some(parse_while_loop(tokens)?));
|
||||
return Ok(Some(parse_while_loop(tokens, cli)?));
|
||||
} else if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::For)) {
|
||||
return Ok(Some(parse_for_loop(tokens)?));
|
||||
return Ok(Some(parse_for_loop(tokens, cli)?));
|
||||
} else if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Loop)) {
|
||||
return Ok(Some(parse_inf_loop(tokens)?));
|
||||
return Ok(Some(parse_inf_loop(tokens, cli)?));
|
||||
} else if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Return)) {
|
||||
return Ok(Some(parse_return(tokens)?));
|
||||
return Ok(Some(parse_return(tokens, cli)?));
|
||||
} else if let Some(kw) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Break)) {
|
||||
let _ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "Expected ; at the end of the expression")?;
|
||||
return Ok(Some(LocBox::new(kw.loc(), Expr::Break)));
|
||||
|
|
@ -82,7 +82,7 @@ pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool
|
|||
let _ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "Expected ; at the end of the expression")?;
|
||||
return Ok(Some(LocBox::new(kw.loc(), Expr::Continue)));
|
||||
} else if let Some(kw) = utils::check(tokens, TokenType::Keyword(Keyword::If)) {
|
||||
return Ok(Some(LocBox::new(&kw.loc().clone(), Expr::If(parse_if(tokens)?))));
|
||||
return Ok(Some(LocBox::new(&kw.loc().clone(), Expr::If(parse_if(tokens, cli)?))));
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -96,17 +96,17 @@ pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool
|
|||
res = parse_ptr_field_access(tokens, res)?;
|
||||
}
|
||||
if utils::check(tokens, TokenType::Delim(Delimiter::ParenL)).is_some() {
|
||||
res = parse_fn_call(tokens, res)?;
|
||||
res = parse_fn_call(tokens, res, cli)?;
|
||||
}
|
||||
if utils::check(tokens, TokenType::Keyword(Keyword::As)).is_some() {
|
||||
res = parse_cast(tokens, res)?;
|
||||
}
|
||||
if utils::check(tokens, TokenType::Delim(Delimiter::SquareL)).is_some() {
|
||||
res = parse_array_index(tokens, res)?;
|
||||
res = parse_array_index(tokens, res, cli)?;
|
||||
}
|
||||
|
||||
if let Some(_) = utils::check_from_many(tokens, BINOP_LIST) {
|
||||
let v = parse_binop(tokens, res, precedence)?;
|
||||
let v = parse_binop(tokens, res, precedence, cli)?;
|
||||
if consume_semi {
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "Expected ; at the end of the expression")?;
|
||||
}
|
||||
|
|
@ -124,9 +124,9 @@ pub fn parse_expr(tokens: &mut Vec<Token>, precedence: usize, consume_semi: bool
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
fn parse_return(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
fn parse_return(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Return), "")?;
|
||||
let item = parse_expr(tokens, 0, true)?;
|
||||
let item = parse_expr(tokens, 0, true, cli)?;
|
||||
Ok(LocBox::new(kw.loc(), Expr::Return(Box::new(item))))
|
||||
}
|
||||
|
||||
|
|
@ -138,10 +138,10 @@ fn parse_cast(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr
|
|||
right: Box::new(typ)
|
||||
}))
|
||||
}
|
||||
fn parse_if(tokens: &mut Vec<Token>) -> Result<IfExpr> {
|
||||
fn parse_if(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<IfExpr> {
|
||||
let loc = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::If), "")?;
|
||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
||||
let Some(test) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(test) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(loc.loc(), "Expected test for if statement, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
|
|
@ -151,7 +151,7 @@ fn parse_if(tokens: &mut Vec<Token>) -> Result<IfExpr> {
|
|||
_ = utils::check_consume(tokens, TokenType::Delim(Delimiter::CurlyR));
|
||||
Block(Vec::new())
|
||||
} else {
|
||||
parse_block(tokens)?
|
||||
parse_block(tokens, cli)?
|
||||
}
|
||||
} else {
|
||||
lerror!(loc.loc(), "Expected '{{'");
|
||||
|
|
@ -159,14 +159,14 @@ fn parse_if(tokens: &mut Vec<Token>) -> Result<IfExpr> {
|
|||
};
|
||||
if let Some(_) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Else)) {
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::If)) {
|
||||
let branch = IfBranchExpr::ElseIf(Box::new(parse_if(tokens)?));
|
||||
let branch = IfBranchExpr::ElseIf(Box::new(parse_if(tokens, cli)?));
|
||||
Ok(IfExpr {
|
||||
test: Box::new(test),
|
||||
body: block,
|
||||
else_if: Some(branch)
|
||||
})
|
||||
} else {
|
||||
let branch = IfBranchExpr::Else(parse_block(tokens)?);
|
||||
let branch = IfBranchExpr::Else(parse_block(tokens, cli)?);
|
||||
Ok(IfExpr {
|
||||
test: Box::new(test),
|
||||
body: block,
|
||||
|
|
@ -181,39 +181,39 @@ fn parse_if(tokens: &mut Vec<Token>) -> Result<IfExpr> {
|
|||
})
|
||||
}
|
||||
}
|
||||
fn parse_while_loop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
fn parse_while_loop(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::While), "")?;
|
||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
||||
let Some(test) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(test) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(kw.loc(), "Expected test comparrison for while loop, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenR), "")?;
|
||||
let block = parse_block(tokens)?;
|
||||
let block = parse_block(tokens, cli)?;
|
||||
Ok(LocBox::new(kw.loc(), Expr::WhileLoop {
|
||||
test: Box::new(test),
|
||||
body: block
|
||||
}))
|
||||
}
|
||||
fn parse_for_loop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
fn parse_for_loop(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::For), "")?;
|
||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
||||
let Some(pre) = parse_item(tokens)? else {
|
||||
let Some(pre) = parse_item(tokens, cli)? else {
|
||||
lerror!(kw.loc(), "Expected init stat for a for loop, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
// Semicolon parsed out by parse_item above
|
||||
let Some(test) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(test) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(kw.loc(), "Expected test comparrison for a for loop, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "");
|
||||
let Some(post) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(post) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(kw.loc(), "Expected post expression (usually an index increment) for a for loop, got nothing");
|
||||
bail!("")
|
||||
};
|
||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenR), "")?;
|
||||
let block = parse_block(tokens)?;
|
||||
let block = parse_block(tokens, cli)?;
|
||||
|
||||
Ok(LocBox::new(kw.loc(), Expr::ForLoop {
|
||||
init: Box::new(pre),
|
||||
|
|
@ -222,16 +222,16 @@ fn parse_for_loop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
|||
body: block
|
||||
}))
|
||||
}
|
||||
fn parse_inf_loop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
fn parse_inf_loop(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Loop), "")?;
|
||||
let block = parse_block(tokens)?;
|
||||
let block = parse_block(tokens, cli)?;
|
||||
Ok(LocBox::new(kw.loc(), Expr::InfLoop { body: block }))
|
||||
}
|
||||
fn parse_fn_call(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr>> {
|
||||
fn parse_fn_call(tokens: &mut Vec<Token>, left: LocBox<Expr>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
match left.inner() {
|
||||
Expr::FieldAccess { .. } |
|
||||
Expr::PtrFieldAccess { .. } => {
|
||||
return parse_member_function_call(tokens, left);
|
||||
return parse_member_function_call(tokens, left, cli);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
|
@ -244,7 +244,7 @@ fn parse_fn_call(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<E
|
|||
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
||||
break;
|
||||
}
|
||||
let Some(param) = parse_expr(tokens, 0, false)? else {break};
|
||||
let Some(param) = parse_expr(tokens, 0, false, cli)? else {break};
|
||||
params.push(param);
|
||||
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
||||
if let None = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
||||
|
|
@ -256,9 +256,9 @@ fn parse_fn_call(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<E
|
|||
_ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenR), "");
|
||||
Ok(LocBox::new(start.loc(), Expr::Call { path: Box::new(left), params: CallParams(params) }))
|
||||
}
|
||||
fn parse_array_index(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr>> {
|
||||
fn parse_array_index(tokens: &mut Vec<Token>, left: LocBox<Expr>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareL), "")?;
|
||||
let Some(idx) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(idx) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(start.loc(), "Expected index for in array index but found nothing.");
|
||||
bail!("")
|
||||
};
|
||||
|
|
@ -288,7 +288,7 @@ fn parse_field_access(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<Loc
|
|||
}))
|
||||
}
|
||||
|
||||
fn parse_member_function_call(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result<LocBox<Expr>> {
|
||||
fn parse_member_function_call(tokens: &mut Vec<Token>, left: LocBox<Expr>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "unreachable")?;
|
||||
let mut params = Vec::new();
|
||||
|
||||
|
|
@ -296,7 +296,7 @@ fn parse_member_function_call(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Re
|
|||
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
||||
break;
|
||||
}
|
||||
let Some(param) = parse_expr(tokens, 0, false)? else {break};
|
||||
let Some(param) = parse_expr(tokens, 0, false, cli)? else {break};
|
||||
params.push(param);
|
||||
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
||||
if let None = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
||||
|
|
@ -331,7 +331,7 @@ fn parse_ptr_field_access(tokens: &mut Vec<Token>, left: LocBox<Expr>) -> Result
|
|||
}))
|
||||
}
|
||||
|
||||
fn parse_literal(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
fn parse_literal(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
if let Some(tkn) = utils::check_consume(tokens, TokenType::Keyword(Keyword::True)) {
|
||||
return Ok(LocBox::new(tkn.loc(), Expr::Literal(String::new(), Literal::Bool(true))));
|
||||
} else
|
||||
|
|
@ -354,28 +354,15 @@ fn parse_literal(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
|||
if let Some(_) = utils::check_consume(tokens, TokenType::Delim(Delimiter::SquareR)) {
|
||||
return Ok(LocBox::new(start.loc(), Expr::Literal(String::new(), Literal::Array(Vec::new()))));
|
||||
}
|
||||
if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Comma) {
|
||||
let first = parse_expr(tokens, 0, false)?;
|
||||
let Some(first) = first else { unreachable!() };
|
||||
/*if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Comma) {
|
||||
|
||||
let mut values = Vec::new();
|
||||
values.push(first);
|
||||
while !tokens.is_empty() {
|
||||
let Some(val) = parse_expr(tokens, 0, false)? else{break};
|
||||
|
||||
values.push(val);
|
||||
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareR), "")?;
|
||||
return Ok(LocBox::new(start.loc(), Expr::Literal(String::new(), Literal::Array(values))));
|
||||
} else if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Semi) {
|
||||
let Some(typ) = parse_expr(tokens, 0, true)? else {
|
||||
} else */
|
||||
if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Semi) {
|
||||
let Some(typ) = parse_expr(tokens, 0, true, cli)? else {
|
||||
lerror!(start.loc(), "Expected value, found nothing");
|
||||
bail!("")
|
||||
};
|
||||
let count = parse_expr(tokens, 0, false)?.unwrap();
|
||||
let count = parse_expr(tokens, 0, false, cli)?.unwrap();
|
||||
|
||||
let Expr::Literal(_, Literal::Number(count)) = count.inner() else {
|
||||
lerror!(count.loc(), "a repeating array accepts only literal numbers for count argument");
|
||||
|
|
@ -387,18 +374,35 @@ fn parse_literal(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
|||
count: count.val
|
||||
})));
|
||||
} else {
|
||||
let first = parse_expr(tokens, 0, false, cli)?;
|
||||
let Some(first) = first else { unreachable!() };
|
||||
|
||||
let mut values = Vec::new();
|
||||
values.push(first);
|
||||
while !tokens.is_empty() {
|
||||
let Some(val) = parse_expr(tokens, 0, false, cli)? else{break};
|
||||
|
||||
values.push(val);
|
||||
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareR), "")?;
|
||||
return Ok(LocBox::new(start.loc(), Expr::Literal(String::new(), Literal::Array(values))));
|
||||
/*
|
||||
if let Some(curr) = tokens.last() {
|
||||
lerror!(start.loc(), "Expected a , or ; as a separator in a literal array (normal, or repeating, respectively), but found {}", curr.tt());
|
||||
} else {
|
||||
lerror!(start.loc(), "Expected a , or ; as a separator in a literal array (normal, or repeating, respectively), but found nothing");
|
||||
}
|
||||
bail!("")
|
||||
*/
|
||||
}
|
||||
}
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn parse_struct_literal(tokens: &mut Vec<Token>, name: Path) -> Result<LocBox<Expr>> {
|
||||
fn parse_struct_literal(tokens: &mut Vec<Token>, name: Path, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::CurlyL), "")?;
|
||||
let mut fields = BTreeMap::new();
|
||||
while !tokens.is_empty() {
|
||||
|
|
@ -408,7 +412,7 @@ fn parse_struct_literal(tokens: &mut Vec<Token>, name: Path) -> Result<LocBox<Ex
|
|||
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?;
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "wtf?")?;
|
||||
let typ = parse_expr(tokens, 0, false)?.unwrap();
|
||||
let typ = parse_expr(tokens, 0, false, cli)?.unwrap();
|
||||
fields.insert(name.tt().unwrap_ident(), typ);
|
||||
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::CurlyR), "")?;
|
||||
|
|
@ -418,9 +422,9 @@ fn parse_struct_literal(tokens: &mut Vec<Token>, name: Path) -> Result<LocBox<Ex
|
|||
Ok(LocBox::new(start.loc(), Expr::Struct(String::new(), StructLit { path: name, fields })))
|
||||
}
|
||||
|
||||
fn parse_group(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
fn parse_group(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
||||
let Some(expr) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(expr) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(start.loc(), "Expected expr found nothing");
|
||||
bail!("")
|
||||
};
|
||||
|
|
@ -445,7 +449,7 @@ fn parse_path(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
|||
Ok(LocBox::new(part.loc(), Expr::Path(Path(buf))))
|
||||
}
|
||||
|
||||
fn parse_unop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||
fn parse_unop(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
let typ = utils::check_consume_or_err_from_many(tokens, &[
|
||||
TokenType::Punct(Punctuation::Not),
|
||||
TokenType::Punct(Punctuation::Plus), // Make number positive
|
||||
|
|
@ -456,7 +460,7 @@ fn parse_unop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
|||
let loc = typ.loc().clone();
|
||||
let TokenType::Punct(typ) = typ.tt().clone() else {unreachable!()};
|
||||
|
||||
let Some(right) = parse_expr(tokens, 5, false)? else {
|
||||
let Some(right) = parse_expr(tokens, 5, false, cli)? else {
|
||||
lerror!(&loc, "Expected expression after unary token, found nothing");
|
||||
bail!("")
|
||||
};
|
||||
|
|
@ -466,7 +470,7 @@ fn parse_unop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
|||
}))
|
||||
}
|
||||
|
||||
fn parse_binop(tokens: &mut Vec<Token>, mut lhs: LocBox<Expr>, precedence: usize) -> Result<LocBox<Expr>> {
|
||||
fn parse_binop(tokens: &mut Vec<Token>, mut lhs: LocBox<Expr>, precedence: usize, cli: &CliArgs) -> Result<LocBox<Expr>> {
|
||||
// TODO: https://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudocode
|
||||
|
||||
loop {
|
||||
|
|
@ -497,7 +501,7 @@ fn parse_binop(tokens: &mut Vec<Token>, mut lhs: LocBox<Expr>, precedence: usize
|
|||
}
|
||||
|
||||
_ = tokens.pop();
|
||||
let Some(rhs) = parse_expr(tokens, rp, false)? else {break;};
|
||||
let Some(rhs) = parse_expr(tokens, rp, false, cli)? else {break;};
|
||||
lhs = LocBox::new(&op_loc, Expr::BinOp {
|
||||
typ: op,
|
||||
left: Box::new(lhs),
|
||||
|
|
@ -511,14 +515,14 @@ fn parse_binop(tokens: &mut Vec<Token>, mut lhs: LocBox<Expr>, precedence: usize
|
|||
|
||||
}
|
||||
|
||||
pub fn parse_block(tokens: &mut Vec<Token>) -> Result<Block> {
|
||||
pub fn parse_block(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<Block> {
|
||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::CurlyL), "")?;
|
||||
let mut items = Vec::new();
|
||||
while !tokens.is_empty() {
|
||||
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyR)) {
|
||||
break;
|
||||
}
|
||||
if let Some(item) = parse_item(tokens)? {
|
||||
if let Some(item) = parse_item(tokens, cli)? {
|
||||
items.push(item);
|
||||
} else {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||
|
||||
use ast::{expr::Block, Ast, Program};
|
||||
|
||||
use crate::tokeniser::{Token, tokentype::*};
|
||||
use crate::{cli::CliArgs, tokeniser::{Token, tokentype::*}};
|
||||
|
||||
pub mod ast;
|
||||
mod expr;
|
||||
|
|
@ -12,11 +12,11 @@ pub mod typ;
|
|||
|
||||
type Result<T> = anyhow::Result<T>;
|
||||
|
||||
pub fn parse_program(mut tokens: Vec<Token>) -> Result<Program> {
|
||||
pub fn parse_program(mut tokens: Vec<Token>, cli: &CliArgs) -> Result<Program> {
|
||||
let mut prog_body = Vec::new();
|
||||
|
||||
while !tokens.is_empty() {
|
||||
if let Some(item) = parse_item(&mut tokens)? {
|
||||
if let Some(item) = parse_item(&mut tokens, cli)? {
|
||||
prog_body.push(item);
|
||||
} else {
|
||||
break
|
||||
|
|
@ -40,11 +40,11 @@ pub fn parse_program(mut tokens: Vec<Token>) -> Result<Program> {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_item(tokens: &mut Vec<Token>) -> Result<Option<Ast>> {
|
||||
if let Some(stat) = stat::parse_statement(tokens)? {
|
||||
fn parse_item(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<Option<Ast>> {
|
||||
if let Some(stat) = stat::parse_statement(tokens, cli)? {
|
||||
return Ok(Some(Ast::Statement(stat)));
|
||||
}
|
||||
if let Some(expr) = expr::parse_expr(tokens, 0, true)? {
|
||||
if let Some(expr) = expr::parse_expr(tokens, 0, true, cli)? {
|
||||
return Ok(Some(Ast::Expr(expr)));
|
||||
}
|
||||
Ok(None)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use anyhow::bail;
|
||||
|
||||
use crate::cli::CliArgs;
|
||||
use crate::common::loc::LocBox;
|
||||
use crate::lerror;
|
||||
use crate::parser::ast::TokenType;
|
||||
use crate::{cli, lerror};
|
||||
use crate::parser::ast::{TString, TokenType};
|
||||
use crate::parser::ast::statement::Let;
|
||||
use crate::parser::expr::parse_expr;
|
||||
use crate::parser::{Delimiter, Ident, Keyword, Punctuation};
|
||||
|
|
@ -15,18 +16,18 @@ use super::ast::statement::{ConstVar, Enum, Function, Statement, StaticVar, Stru
|
|||
|
||||
type Result<T> = anyhow::Result<T>;
|
||||
|
||||
pub fn parse_statement(tokens: &mut Vec<Token>) -> Result<Option<LocBox<Statement>>> {
|
||||
pub fn parse_statement(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<Option<LocBox<Statement>>> {
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Fn)) {
|
||||
Ok(Some(parse_fn(tokens)?))
|
||||
Ok(Some(parse_fn(tokens, cli)?))
|
||||
} else
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Type)) {
|
||||
Ok(Some(parse_type_alias(tokens)?))
|
||||
} else
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Const)) {
|
||||
Ok(Some(parse_constant(tokens)?))
|
||||
Ok(Some(parse_constant(tokens, cli)?))
|
||||
} else
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Static)) {
|
||||
Ok(Some(parse_static(tokens)?))
|
||||
Ok(Some(parse_static(tokens, cli)?))
|
||||
} else
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Struct)) {
|
||||
Ok(Some(parse_struct(tokens)?))
|
||||
|
|
@ -35,13 +36,42 @@ pub fn parse_statement(tokens: &mut Vec<Token>) -> Result<Option<LocBox<Statemen
|
|||
Ok(Some(parse_enum(tokens)?))
|
||||
} else
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Let)) {
|
||||
Ok(Some(parse_let(tokens)?))
|
||||
Ok(Some(parse_let(tokens, cli)?))
|
||||
} else
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Include)) {
|
||||
Ok(Some(parse_include(tokens, cli)?))
|
||||
} else {
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_include(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Include), "")?;
|
||||
let TokenType::String(include_path) = utils::check_consume_or_err(tokens, TokenType::String(TString::default()), "")?.tt().clone() else {panic!()};
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||
let cwd = std::env::current_dir()?;
|
||||
let mut found = false;
|
||||
for p in &cli.include_paths {
|
||||
let path = cwd.join(p);
|
||||
let path = path.join(&include_path.val);
|
||||
if path.exists() {
|
||||
let data = std::fs::read_to_string(&path)?;
|
||||
let mut tokens_imp = crate::tokeniser::tokenise(&data, &path.to_string_lossy().to_string())?;
|
||||
tokens.append(&mut tokens_imp);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
lerror!(kw.loc(), "Could not find file {:?}", include_path.val);
|
||||
bail!("")
|
||||
}
|
||||
|
||||
Ok(LocBox::new(kw.loc(), Statement::Include))
|
||||
}
|
||||
|
||||
fn parse_enum(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Enum), "")?;
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
|
|
@ -92,14 +122,14 @@ fn parse_struct(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
|||
Ok(LocBox::new(kw.loc(), Statement::Struct(Struct { name, fields })))
|
||||
}
|
||||
|
||||
fn parse_static(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
fn parse_static(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Static), "")?;
|
||||
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "")?;
|
||||
let typ = parse_type(tokens)?;
|
||||
let eq = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Eq), "")?;
|
||||
let Some(val) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(val) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(eq.loc(), "Expected expression found nothing");
|
||||
bail!("")
|
||||
};
|
||||
|
|
@ -107,7 +137,7 @@ fn parse_static(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
|||
Ok(LocBox::new(kw.loc(), Statement::StaticVar(StaticVar { name, typ, val })))
|
||||
}
|
||||
|
||||
fn parse_let(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
fn parse_let(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Let), "")?;
|
||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||
let mut typ = None;
|
||||
|
|
@ -116,7 +146,7 @@ fn parse_let(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
|||
typ = Some(parse_type(tokens)?);
|
||||
}
|
||||
if let Some(eq) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Eq)) {
|
||||
let Some(_val) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(_val) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(eq.loc(), "Expected expression found nothing");
|
||||
bail!("")
|
||||
};
|
||||
|
|
@ -125,7 +155,7 @@ fn parse_let(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
|||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||
Ok(LocBox::new(kw.loc(), Statement::Let(Let{ name, typ, val })))
|
||||
}
|
||||
fn parse_constant(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
fn parse_constant(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Statement>> {
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Const), "")?;
|
||||
|
||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Fn)) {
|
||||
|
|
@ -135,7 +165,7 @@ fn parse_constant(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
|||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "")?;
|
||||
let typ = parse_type(tokens)?;
|
||||
let eq = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Eq), "")?;
|
||||
let Some(val) = parse_expr(tokens, 0, false)? else {
|
||||
let Some(val) = parse_expr(tokens, 0, false, cli)? else {
|
||||
lerror!(eq.loc(), "Expected expression found nothing");
|
||||
bail!("")
|
||||
};
|
||||
|
|
@ -153,7 +183,7 @@ fn parse_type_alias(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
|||
Ok(LocBox::new(kw.loc(), Statement::TypeAlias(TypeAlias { name, typ })))
|
||||
}
|
||||
|
||||
fn parse_fn(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||
fn parse_fn(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<LocBox<Statement>> {
|
||||
// Just remove the kw since we checked it before
|
||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Fn), "")?;
|
||||
|
||||
|
|
@ -173,7 +203,7 @@ fn parse_fn(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
|||
}
|
||||
let body;
|
||||
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyL)) {
|
||||
body = Some(parse_block(tokens)?);
|
||||
body = Some(parse_block(tokens, cli)?);
|
||||
} else {
|
||||
// Check if its just a declaration
|
||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::{Result, bail};
|
||||
|
||||
use crate::{common::loc::LocBox, lerror, parser::{Delimiter, ast::{expr::Expr, literal::Literal}}, tokeniser::Token};
|
||||
use crate::{cli::CliArgs, common::loc::LocBox, lerror, parser::{Delimiter, ast::{expr::Expr, literal::Literal}}, tokeniser::Token};
|
||||
|
||||
use super::{ast::{typ::Type, TokenType}, expr::parse_expr, utils, Keyword, Punctuation};
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ pub fn parse_type(tokens: &mut Vec<Token>) -> Result<LocBox<Type>> {
|
|||
}
|
||||
let itm_typ = parse_type(tokens)?;
|
||||
if let Some(_) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Semi)) {
|
||||
let count = parse_expr(tokens, 0, false)?.unwrap();
|
||||
let count = parse_expr(tokens, 0, false, &CliArgs::default())?.unwrap();
|
||||
|
||||
match count.inner() {
|
||||
Expr::Literal(_, Literal::Number(_)) |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{common::{Loc, loc::LocBox}, parser::ast::{Ast, Ident, Program, Punctuation, expr::{Expr, IfBranchExpr}, literal::Literal, statement::{ConstDataTyp, Function, Statement, get_constant_data_as_bytes}, typ::Type}, targets::Target};
|
||||
use std::{collections::HashMap, fs::File, io::Write};
|
||||
use std::{collections::HashMap, fs::File, io::Write, process};
|
||||
pub struct AsmGen;
|
||||
|
||||
const RUNTIME_CODE: &'static str = include_str!("./runtime.s");
|
||||
|
|
@ -17,8 +17,10 @@ impl Target for AsmGen {
|
|||
fn write_code(&mut self, program: &crate::parser::ast::Program, f: &mut File) -> anyhow::Result<()> {
|
||||
writeln!(f, "bits 64")?;
|
||||
writeln!(f, "global _start")?;
|
||||
self.write_extern_func_decls(program, f)?;
|
||||
writeln!(f, "section .text")?;
|
||||
writeln!(f, "{}", RUNTIME_CODE)?;
|
||||
|
||||
for item in &program.ast.0 {
|
||||
match item {
|
||||
Ast::Statement(stat) => {
|
||||
|
|
@ -220,6 +222,20 @@ impl AsmGen {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
pub fn write_extern_func_decls(&self, program: &Program, f: &mut File) -> anyhow::Result<()> {
|
||||
for (name, func) in &program.functions {
|
||||
match func.inner().qual_extern {
|
||||
Some(_) if func.inner().body.is_some() => {
|
||||
writeln!(f, "global {name}")?;
|
||||
}
|
||||
Some(_) if func.inner().body.is_none() => {
|
||||
writeln!(f, "extern {name}")?;
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn write_ast(&self, program: &Program, f: &mut impl Write, fc: &mut FunctionCtx, ast: &Ast) -> anyhow::Result<()> {
|
||||
match ast {
|
||||
Ast::Expr(expr) => self.write_expr(program, f, fc, expr.inner())?,
|
||||
|
|
@ -529,7 +545,6 @@ impl AsmGen {
|
|||
}
|
||||
}
|
||||
Expr::Path(path) => {
|
||||
dbg!(&path);
|
||||
let ident = path.0.last().unwrap().clone();
|
||||
if let Some(var) = fc.get(&ident) {
|
||||
match var {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
; generated with godbolt: https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1AB9U8lJL6yAngGVG6AMKpaAVxYMQAJlIOAMngMmABy7gBGmMQgAMw%2BAA6oCoS2DM5uHt6kCUk2AgFBoSwRUbEWmFa5DEIETMQEae6ePpaY1inVtQT5IeGRMc01dQ0ZA53dhcX9AJQWqK7EyOwcAPQAVADUACoAnnGY69tzxOtoWOsIkZik6yTrtKhM6OuG65iqrHH0AHTrq8sApBoAIL/LzRQLINxnf7RRwKAjoWh4MJfBAw7CAkFgiFQ/YwuEI2yo9GY0HghiQ1zQ2Hw/CCYnRDHAzFJABemGMBHWLG2Cl5olotAgrkCBAAHJznsRgMY0K5BNcRYIJVy%2BQoBbRjAx3NcAG6oPBPVarWrABRTdb/ADsACFMesHes2RyucRMAQYXbgY71m7gHh4ZEnXh2ZLiExVM8FCwIKCvOHVHGLTCACJO/liTXalie%2B2Ov0BghB51h/BRmNx4j4JOW6JpjS5735zD%2BwPHEuupLl2NeeNJGup9YN6JeoE%2Bgtt4Oh13oSNMaM9%2BOzgd1oeNsfN1tF9shl2%2BrgabuVg8r%2Bvr8ctwvF3dhsUO%2BcV3vEMU12tnkd5h0T7dTvfEACc94LpW/6voOw6jp%2B6x4FQ6wQKaspzIItbYEOFpVngb5wR2Uymgo/wAKw2g2BEpuejowXBCFysh6LrFw6FdoOEA4XhhE2lwhFkR%2BTYOpR8HSoh8pcnRXjobOWEsTeBC4dK%2BFEV4XHkXxsECTKNEiYy6zROhB6SaxcnsdESk8RuKlUYJGkoeskjoXe%2BnSbJZrsZIJmjj6/HUUhmmoQR6GAQ505OfJNoEW5pK8eW6z6gYNj0HBUE%2BnGaoanGiWOiAlq9qmTBxhAboyelDqZXGuW9vlEYzFlXhkeVGFVXGQh5cQSQNb26DNbOMxFY6lbNQebXxs1YqDcQzX/lMPUlU%2ByCJr21zHpx83VWwLAkNsaWRZNplQQV8wML67rrtaKYcDMtCcARvCeBwWikKgnCOE6RyLFl0Q8KQBCaGdMwANYgARGj6JwkjXd992cLwCggEDX23WdpBwLASBoCwcR0JE5CUKj6P0FEyDAFwBE%2BDQtDbtDEBhODYSBLU2ycB9NPMMQ2wAPJhNorRwx9qNsIIrMMLQ9Pw6QWBhK4wCOJm0PcLwWAsIYwDiCL%2BBum0uqYDLd1vK0rhFgzvCiuU4NImE4Ys84WDgwQxB4CwBukBrxBhIkmAppgCtGEiRjfTMVAGGaABqeCYAA7qzew3R9/CCCIYjsFIMiCIoKjqCLuhcPoisgKYsr6Mi0OQDMqBxJUMsALSs9EvCoE7ttYIXEAzC0bR2BADjDJ4XA%2BP4gQ9EUfTvVkiTJAInd6Nko8MOMvRRJnLeVB0QwuI0EjNOUXPtIMXR9xMg/z9v48H2Mu%2BzxIzcvQn52XWDIsPRw6yqGKABs5fP5I6zAMgyD0QRXxeHBXAhBbhkgYrwOGWgph/QBkDC6HBQakBunde%2BUMYafV9tfDgXhb7IMhug%2BGUDHaRCSHYSQQA
|
||||
; removed "qword ptr" and replaced with "qword"
|
||||
syscall:
|
||||
__INTERNAL_syscall:
|
||||
mov ecx, edi
|
||||
mov r11, rdx
|
||||
movzx eax, sil
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ fn validate_stat(prog: &mut Program, stat: &mut LocBox<Statement>, current_state
|
|||
Statement::Enum(enm) => validate_enum(prog, enm)?,
|
||||
Statement::Struct(strct) => validate_struct(prog, strct)?,
|
||||
Statement::TypeAlias(alias) => validate_type_alias(prog, alias)?,
|
||||
Statement::Let(_) => unreachable!()
|
||||
Statement::Let(_) => unreachable!(),
|
||||
Statement::Include => (),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -183,8 +184,6 @@ pub fn validate_expr(prog: &mut Program, expr: &mut Expr) -> anyhow::Result<Opti
|
|||
let t = validate_expr(prog, param.inner_mut())?.clone();
|
||||
match t {
|
||||
Some(t) => {
|
||||
dbg!(&t);
|
||||
dbg!(&ft);
|
||||
if t.get_absolute_value(prog)? != ft.get_absolute_value(prog)? {
|
||||
lerror!(param.loc(), "expected {ft}, got {}", t);
|
||||
bail!("")
|
||||
|
|
@ -563,6 +562,7 @@ fn check_that_types_exist_for_items(prog: &mut Program, items: &Vec<Ast>) -> any
|
|||
}
|
||||
}
|
||||
},
|
||||
Statement::Include |
|
||||
Statement::Let { .. } => (),
|
||||
Statement::ConstVar(var) => {
|
||||
validate_type(prog, &var.typ)?;
|
||||
|
|
@ -653,6 +653,7 @@ fn collect_types_and_constants(prog: &mut Program, items: &mut Vec<Ast>) {
|
|||
let typ = alias.clone().typ.inner_mut().clone();
|
||||
prog.types.insert(alias.name.clone(), LocBox::new(stat.loc(), typ));
|
||||
}
|
||||
Statement::Include |
|
||||
Statement::Let { .. } => (),
|
||||
Statement::ConstVar(var) => {
|
||||
prog.const_vars.insert(var.name.clone(), var.clone());
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ lazy_static!(
|
|||
("bool", (1, true)),
|
||||
].into();
|
||||
pub static ref FUNCTIONS: HashMap<&'static str, (Vec<(&'static str, &'static str)>, &'static str)> = [
|
||||
("syscall", (vec![
|
||||
("__INTERNAL_syscall", (vec![
|
||||
("arg_count", "u8"),
|
||||
("sc_num", "u8"),
|
||||
("args", "&[&void]")
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user