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
|
/target
|
||||||
/*.c
|
/*.c
|
||||||
/*.s
|
/*.s
|
||||||
|
/*.o
|
||||||
/*.ssa
|
/*.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;
|
use crate::logger::Level;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, clap::Parser)]
|
#[derive(Debug, Default, clap::Parser)]
|
||||||
pub struct CliArgs {
|
pub struct CliArgs {
|
||||||
/// Output more info, will get overwritten if -q|--quiet is specified
|
/// Output more info, will get overwritten if -q|--quiet is specified
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
|
|
@ -13,6 +13,8 @@ pub struct CliArgs {
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
#[arg(long, short, value_parser=crate::targets::get_all_targets(), default_value_t=crate::targets::get_default_target())]
|
#[arg(long, short, value_parser=crate::targets::get_all_targets(), default_value_t=crate::targets::get_default_target())]
|
||||||
pub target: String,
|
pub target: String,
|
||||||
|
#[arg(long="include", short='I', default_values=["include"])]
|
||||||
|
pub include_paths: Vec<String>,
|
||||||
/// Output file
|
/// Output file
|
||||||
#[arg(long, short, default_value="a.out")]
|
#[arg(long, short, default_value="a.out")]
|
||||||
pub output: String,
|
pub output: String,
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,10 @@ fn main() -> anyhow::Result<()> {
|
||||||
let data = std::fs::read_to_string(&fp).unwrap();
|
let data = std::fs::read_to_string(&fp).unwrap();
|
||||||
info!("Tokenising {file}");
|
info!("Tokenising {file}");
|
||||||
let tokens = mclangc::tokeniser::tokenise(&data, &file)?;
|
let tokens = mclangc::tokeniser::tokenise(&data, &file)?;
|
||||||
|
// dbg!(&tokens);
|
||||||
info!("Parsing {file}");
|
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}");
|
info!("Validating {file}");
|
||||||
mclangc::validator::validate_code(&mut prog)?;
|
mclangc::validator::validate_code(&mut prog)?;
|
||||||
// dbg!(&prog.literals);
|
// dbg!(&prog.literals);
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ pub enum Statement {
|
||||||
Enum(Enum),
|
Enum(Enum),
|
||||||
ConstVar(ConstVar),
|
ConstVar(ConstVar),
|
||||||
StaticVar(StaticVar),
|
StaticVar(StaticVar),
|
||||||
|
Include,
|
||||||
Let(Let),
|
Let(Let),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
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};
|
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),
|
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)) {
|
let res = if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::ParenL)) {
|
||||||
Some(parse_group(tokens)?)
|
Some(parse_group(tokens, cli)?)
|
||||||
} else
|
} else
|
||||||
if let Some(_) = utils::check(tokens, TokenType::ident("")) {
|
if let Some(_) = utils::check(tokens, TokenType::ident("")) {
|
||||||
let p = parse_path(tokens)?;
|
let p = parse_path(tokens)?;
|
||||||
if let Some(t) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyL)) {
|
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 {
|
} else {
|
||||||
Some(p)
|
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::Ampersand),
|
||||||
TokenType::Punct(Punctuation::Star),
|
TokenType::Punct(Punctuation::Star),
|
||||||
]) {
|
]) {
|
||||||
Some(parse_unop(tokens)?)
|
Some(parse_unop(tokens, cli)?)
|
||||||
} else
|
} else
|
||||||
if let Some(_) = utils::check_from_many(tokens, &[
|
if let Some(_) = utils::check_from_many(tokens, &[
|
||||||
TokenType::string("", false),
|
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::True),
|
||||||
TokenType::Keyword(Keyword::False)
|
TokenType::Keyword(Keyword::False)
|
||||||
]) {
|
]) {
|
||||||
Some(parse_literal(tokens)?)
|
Some(parse_literal(tokens, cli)?)
|
||||||
} else if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::While)) {
|
} 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)) {
|
} 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)) {
|
} 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)) {
|
} 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)) {
|
} 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")?;
|
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)));
|
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")?;
|
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)));
|
return Ok(Some(LocBox::new(kw.loc(), Expr::Continue)));
|
||||||
} else if let Some(kw) = utils::check(tokens, TokenType::Keyword(Keyword::If)) {
|
} 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 {
|
} else {
|
||||||
None
|
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)?;
|
res = parse_ptr_field_access(tokens, res)?;
|
||||||
}
|
}
|
||||||
if utils::check(tokens, TokenType::Delim(Delimiter::ParenL)).is_some() {
|
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() {
|
if utils::check(tokens, TokenType::Keyword(Keyword::As)).is_some() {
|
||||||
res = parse_cast(tokens, res)?;
|
res = parse_cast(tokens, res)?;
|
||||||
}
|
}
|
||||||
if utils::check(tokens, TokenType::Delim(Delimiter::SquareL)).is_some() {
|
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) {
|
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 {
|
if consume_semi {
|
||||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "Expected ; at the end of the expression")?;
|
_ = 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)
|
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 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))))
|
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)
|
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 loc = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::If), "")?;
|
||||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
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");
|
lerror!(loc.loc(), "Expected test for if statement, got nothing");
|
||||||
bail!("")
|
bail!("")
|
||||||
};
|
};
|
||||||
|
|
@ -151,7 +151,7 @@ fn parse_if(tokens: &mut Vec<Token>) -> Result<IfExpr> {
|
||||||
_ = utils::check_consume(tokens, TokenType::Delim(Delimiter::CurlyR));
|
_ = utils::check_consume(tokens, TokenType::Delim(Delimiter::CurlyR));
|
||||||
Block(Vec::new())
|
Block(Vec::new())
|
||||||
} else {
|
} else {
|
||||||
parse_block(tokens)?
|
parse_block(tokens, cli)?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lerror!(loc.loc(), "Expected '{{'");
|
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_consume(tokens, TokenType::Keyword(Keyword::Else)) {
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::If)) {
|
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 {
|
Ok(IfExpr {
|
||||||
test: Box::new(test),
|
test: Box::new(test),
|
||||||
body: block,
|
body: block,
|
||||||
else_if: Some(branch)
|
else_if: Some(branch)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let branch = IfBranchExpr::Else(parse_block(tokens)?);
|
let branch = IfBranchExpr::Else(parse_block(tokens, cli)?);
|
||||||
Ok(IfExpr {
|
Ok(IfExpr {
|
||||||
test: Box::new(test),
|
test: Box::new(test),
|
||||||
body: block,
|
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 kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::While), "")?;
|
||||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
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");
|
lerror!(kw.loc(), "Expected test comparrison for while loop, got nothing");
|
||||||
bail!("")
|
bail!("")
|
||||||
};
|
};
|
||||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenR), "")?;
|
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 {
|
Ok(LocBox::new(kw.loc(), Expr::WhileLoop {
|
||||||
test: Box::new(test),
|
test: Box::new(test),
|
||||||
body: block
|
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 kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::For), "")?;
|
||||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "")?;
|
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");
|
lerror!(kw.loc(), "Expected init stat for a for loop, got nothing");
|
||||||
bail!("")
|
bail!("")
|
||||||
};
|
};
|
||||||
// Semicolon parsed out by parse_item above
|
// 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");
|
lerror!(kw.loc(), "Expected test comparrison for a for loop, got nothing");
|
||||||
bail!("")
|
bail!("")
|
||||||
};
|
};
|
||||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "");
|
_ = 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");
|
lerror!(kw.loc(), "Expected post expression (usually an index increment) for a for loop, got nothing");
|
||||||
bail!("")
|
bail!("")
|
||||||
};
|
};
|
||||||
let _ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenR), "")?;
|
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 {
|
Ok(LocBox::new(kw.loc(), Expr::ForLoop {
|
||||||
init: Box::new(pre),
|
init: Box::new(pre),
|
||||||
|
|
@ -222,16 +222,16 @@ fn parse_for_loop(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||||
body: block
|
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 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 }))
|
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() {
|
match left.inner() {
|
||||||
Expr::FieldAccess { .. } |
|
Expr::FieldAccess { .. } |
|
||||||
Expr::PtrFieldAccess { .. } => {
|
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)) {
|
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
||||||
break;
|
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);
|
params.push(param);
|
||||||
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
||||||
if let None = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
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), "");
|
_ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenR), "");
|
||||||
Ok(LocBox::new(start.loc(), Expr::Call { path: Box::new(left), params: CallParams(params) }))
|
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 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.");
|
lerror!(start.loc(), "Expected index for in array index but found nothing.");
|
||||||
bail!("")
|
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 start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::ParenL), "unreachable")?;
|
||||||
let mut params = Vec::new();
|
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)) {
|
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
||||||
break;
|
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);
|
params.push(param);
|
||||||
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
||||||
if let None = utils::check(tokens, TokenType::Delim(Delimiter::ParenR)) {
|
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)) {
|
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))));
|
return Ok(LocBox::new(tkn.loc(), Expr::Literal(String::new(), Literal::Bool(true))));
|
||||||
} else
|
} 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)) {
|
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()))));
|
return Ok(LocBox::new(start.loc(), Expr::Literal(String::new(), Literal::Array(Vec::new()))));
|
||||||
}
|
}
|
||||||
if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Comma) {
|
/*if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Comma) {
|
||||||
let first = parse_expr(tokens, 0, false)?;
|
|
||||||
let Some(first) = first else { unreachable!() };
|
} else */
|
||||||
|
if *tokens[tokens.len()-2].tt() == TokenType::Punct(Punctuation::Semi) {
|
||||||
let mut values = Vec::new();
|
let Some(typ) = parse_expr(tokens, 0, true, cli)? else {
|
||||||
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 {
|
|
||||||
lerror!(start.loc(), "Expected value, found nothing");
|
lerror!(start.loc(), "Expected value, found nothing");
|
||||||
bail!("")
|
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 {
|
let Expr::Literal(_, Literal::Number(count)) = count.inner() else {
|
||||||
lerror!(count.loc(), "a repeating array accepts only literal numbers for count argument");
|
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
|
count: count.val
|
||||||
})));
|
})));
|
||||||
} else {
|
} 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() {
|
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());
|
lerror!(start.loc(), "Expected a , or ; as a separator in a literal array (normal, or repeating, respectively), but found {}", curr.tt());
|
||||||
} else {
|
} else {
|
||||||
lerror!(start.loc(), "Expected a , or ; as a separator in a literal array (normal, or repeating, respectively), but found nothing");
|
lerror!(start.loc(), "Expected a , or ; as a separator in a literal array (normal, or repeating, respectively), but found nothing");
|
||||||
}
|
}
|
||||||
bail!("")
|
bail!("")
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unreachable!()
|
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 start = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::CurlyL), "")?;
|
||||||
let mut fields = BTreeMap::new();
|
let mut fields = BTreeMap::new();
|
||||||
while !tokens.is_empty() {
|
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(""), "")?;
|
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?;
|
||||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "wtf?")?;
|
_ = 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);
|
fields.insert(name.tt().unwrap_ident(), typ);
|
||||||
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
if let None = utils::check_consume(tokens, TokenType::Punct(Punctuation::Comma)) {
|
||||||
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::CurlyR), "")?;
|
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 })))
|
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 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");
|
lerror!(start.loc(), "Expected expr found nothing");
|
||||||
bail!("")
|
bail!("")
|
||||||
};
|
};
|
||||||
|
|
@ -445,7 +449,7 @@ fn parse_path(tokens: &mut Vec<Token>) -> Result<LocBox<Expr>> {
|
||||||
Ok(LocBox::new(part.loc(), Expr::Path(Path(buf))))
|
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, &[
|
let typ = utils::check_consume_or_err_from_many(tokens, &[
|
||||||
TokenType::Punct(Punctuation::Not),
|
TokenType::Punct(Punctuation::Not),
|
||||||
TokenType::Punct(Punctuation::Plus), // Make number positive
|
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 loc = typ.loc().clone();
|
||||||
let TokenType::Punct(typ) = typ.tt().clone() else {unreachable!()};
|
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");
|
lerror!(&loc, "Expected expression after unary token, found nothing");
|
||||||
bail!("")
|
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
|
// TODO: https://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudocode
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -497,7 +501,7 @@ fn parse_binop(tokens: &mut Vec<Token>, mut lhs: LocBox<Expr>, precedence: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = tokens.pop();
|
_ = 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 {
|
lhs = LocBox::new(&op_loc, Expr::BinOp {
|
||||||
typ: op,
|
typ: op,
|
||||||
left: Box::new(lhs),
|
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), "")?;
|
utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::CurlyL), "")?;
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
while !tokens.is_empty() {
|
while !tokens.is_empty() {
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyR)) {
|
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyR)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some(item) = parse_item(tokens)? {
|
if let Some(item) = parse_item(tokens, cli)? {
|
||||||
items.push(item);
|
items.push(item);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use ast::{expr::Block, Ast, Program};
|
use ast::{expr::Block, Ast, Program};
|
||||||
|
|
||||||
use crate::tokeniser::{Token, tokentype::*};
|
use crate::{cli::CliArgs, tokeniser::{Token, tokentype::*}};
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
mod expr;
|
mod expr;
|
||||||
|
|
@ -12,11 +12,11 @@ pub mod typ;
|
||||||
|
|
||||||
type Result<T> = anyhow::Result<T>;
|
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();
|
let mut prog_body = Vec::new();
|
||||||
|
|
||||||
while !tokens.is_empty() {
|
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);
|
prog_body.push(item);
|
||||||
} else {
|
} else {
|
||||||
break
|
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>> {
|
fn parse_item(tokens: &mut Vec<Token>, cli: &CliArgs) -> Result<Option<Ast>> {
|
||||||
if let Some(stat) = stat::parse_statement(tokens)? {
|
if let Some(stat) = stat::parse_statement(tokens, cli)? {
|
||||||
return Ok(Some(Ast::Statement(stat)));
|
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)));
|
return Ok(Some(Ast::Expr(expr)));
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
|
|
||||||
|
use crate::cli::CliArgs;
|
||||||
use crate::common::loc::LocBox;
|
use crate::common::loc::LocBox;
|
||||||
use crate::lerror;
|
use crate::{cli, lerror};
|
||||||
use crate::parser::ast::TokenType;
|
use crate::parser::ast::{TString, TokenType};
|
||||||
use crate::parser::ast::statement::Let;
|
use crate::parser::ast::statement::Let;
|
||||||
use crate::parser::expr::parse_expr;
|
use crate::parser::expr::parse_expr;
|
||||||
use crate::parser::{Delimiter, Ident, Keyword, Punctuation};
|
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>;
|
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)) {
|
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Fn)) {
|
||||||
Ok(Some(parse_fn(tokens)?))
|
Ok(Some(parse_fn(tokens, cli)?))
|
||||||
} else
|
} else
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Type)) {
|
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Type)) {
|
||||||
Ok(Some(parse_type_alias(tokens)?))
|
Ok(Some(parse_type_alias(tokens)?))
|
||||||
} else
|
} else
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Const)) {
|
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Const)) {
|
||||||
Ok(Some(parse_constant(tokens)?))
|
Ok(Some(parse_constant(tokens, cli)?))
|
||||||
} else
|
} else
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Static)) {
|
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Static)) {
|
||||||
Ok(Some(parse_static(tokens)?))
|
Ok(Some(parse_static(tokens, cli)?))
|
||||||
} else
|
} else
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Struct)) {
|
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Struct)) {
|
||||||
Ok(Some(parse_struct(tokens)?))
|
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)?))
|
Ok(Some(parse_enum(tokens)?))
|
||||||
} else
|
} else
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Let)) {
|
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 {
|
} else {
|
||||||
|
|
||||||
Ok(None)
|
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>> {
|
fn parse_enum(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Enum), "")?;
|
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();
|
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 })))
|
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 kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Static), "")?;
|
||||||
|
|
||||||
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
let name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "")?;
|
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "")?;
|
||||||
let typ = parse_type(tokens)?;
|
let typ = parse_type(tokens)?;
|
||||||
let eq = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Eq), "")?;
|
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");
|
lerror!(eq.loc(), "Expected expression found nothing");
|
||||||
bail!("")
|
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 })))
|
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 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 name = utils::check_consume_or_err(tokens, TokenType::ident(""), "")?.tt().unwrap_ident();
|
||||||
let mut typ = None;
|
let mut typ = None;
|
||||||
|
|
@ -116,7 +146,7 @@ fn parse_let(tokens: &mut Vec<Token>) -> Result<LocBox<Statement>> {
|
||||||
typ = Some(parse_type(tokens)?);
|
typ = Some(parse_type(tokens)?);
|
||||||
}
|
}
|
||||||
if let Some(eq) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Eq)) {
|
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");
|
lerror!(eq.loc(), "Expected expression found nothing");
|
||||||
bail!("")
|
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), "")?;
|
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||||
Ok(LocBox::new(kw.loc(), Statement::Let(Let{ name, typ, val })))
|
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), "")?;
|
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Const), "")?;
|
||||||
|
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Keyword(Keyword::Fn)) {
|
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), "")?;
|
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Colon), "")?;
|
||||||
let typ = parse_type(tokens)?;
|
let typ = parse_type(tokens)?;
|
||||||
let eq = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Eq), "")?;
|
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");
|
lerror!(eq.loc(), "Expected expression found nothing");
|
||||||
bail!("")
|
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 })))
|
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
|
// Just remove the kw since we checked it before
|
||||||
let kw = utils::check_consume_or_err(tokens, TokenType::Keyword(Keyword::Fn), "")?;
|
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;
|
let body;
|
||||||
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyL)) {
|
if let Some(_) = utils::check(tokens, TokenType::Delim(Delimiter::CurlyL)) {
|
||||||
body = Some(parse_block(tokens)?);
|
body = Some(parse_block(tokens, cli)?);
|
||||||
} else {
|
} else {
|
||||||
// Check if its just a declaration
|
// Check if its just a declaration
|
||||||
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
_ = utils::check_consume_or_err(tokens, TokenType::Punct(Punctuation::Semi), "")?;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::{Result, bail};
|
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};
|
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)?;
|
let itm_typ = parse_type(tokens)?;
|
||||||
if let Some(_) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Semi)) {
|
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() {
|
match count.inner() {
|
||||||
Expr::Literal(_, Literal::Number(_)) |
|
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 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;
|
pub struct AsmGen;
|
||||||
|
|
||||||
const RUNTIME_CODE: &'static str = include_str!("./runtime.s");
|
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<()> {
|
fn write_code(&mut self, program: &crate::parser::ast::Program, f: &mut File) -> anyhow::Result<()> {
|
||||||
writeln!(f, "bits 64")?;
|
writeln!(f, "bits 64")?;
|
||||||
writeln!(f, "global _start")?;
|
writeln!(f, "global _start")?;
|
||||||
|
self.write_extern_func_decls(program, f)?;
|
||||||
writeln!(f, "section .text")?;
|
writeln!(f, "section .text")?;
|
||||||
writeln!(f, "{}", RUNTIME_CODE)?;
|
writeln!(f, "{}", RUNTIME_CODE)?;
|
||||||
|
|
||||||
for item in &program.ast.0 {
|
for item in &program.ast.0 {
|
||||||
match item {
|
match item {
|
||||||
Ast::Statement(stat) => {
|
Ast::Statement(stat) => {
|
||||||
|
|
@ -220,6 +222,20 @@ impl AsmGen {
|
||||||
|
|
||||||
Ok(())
|
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<()> {
|
pub fn write_ast(&self, program: &Program, f: &mut impl Write, fc: &mut FunctionCtx, ast: &Ast) -> anyhow::Result<()> {
|
||||||
match ast {
|
match ast {
|
||||||
Ast::Expr(expr) => self.write_expr(program, f, fc, expr.inner())?,
|
Ast::Expr(expr) => self.write_expr(program, f, fc, expr.inner())?,
|
||||||
|
|
@ -529,7 +545,6 @@ impl AsmGen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Path(path) => {
|
Expr::Path(path) => {
|
||||||
dbg!(&path);
|
|
||||||
let ident = path.0.last().unwrap().clone();
|
let ident = path.0.last().unwrap().clone();
|
||||||
if let Some(var) = fc.get(&ident) {
|
if let Some(var) = fc.get(&ident) {
|
||||||
match var {
|
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
|
; 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"
|
; removed "qword ptr" and replaced with "qword"
|
||||||
syscall:
|
__INTERNAL_syscall:
|
||||||
mov ecx, edi
|
mov ecx, edi
|
||||||
mov r11, rdx
|
mov r11, rdx
|
||||||
movzx eax, sil
|
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::Enum(enm) => validate_enum(prog, enm)?,
|
||||||
Statement::Struct(strct) => validate_struct(prog, strct)?,
|
Statement::Struct(strct) => validate_struct(prog, strct)?,
|
||||||
Statement::TypeAlias(alias) => validate_type_alias(prog, alias)?,
|
Statement::TypeAlias(alias) => validate_type_alias(prog, alias)?,
|
||||||
Statement::Let(_) => unreachable!()
|
Statement::Let(_) => unreachable!(),
|
||||||
|
Statement::Include => (),
|
||||||
}
|
}
|
||||||
Ok(())
|
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();
|
let t = validate_expr(prog, param.inner_mut())?.clone();
|
||||||
match t {
|
match t {
|
||||||
Some(t) => {
|
Some(t) => {
|
||||||
dbg!(&t);
|
|
||||||
dbg!(&ft);
|
|
||||||
if t.get_absolute_value(prog)? != ft.get_absolute_value(prog)? {
|
if t.get_absolute_value(prog)? != ft.get_absolute_value(prog)? {
|
||||||
lerror!(param.loc(), "expected {ft}, got {}", t);
|
lerror!(param.loc(), "expected {ft}, got {}", t);
|
||||||
bail!("")
|
bail!("")
|
||||||
|
|
@ -563,6 +562,7 @@ fn check_that_types_exist_for_items(prog: &mut Program, items: &Vec<Ast>) -> any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Statement::Include |
|
||||||
Statement::Let { .. } => (),
|
Statement::Let { .. } => (),
|
||||||
Statement::ConstVar(var) => {
|
Statement::ConstVar(var) => {
|
||||||
validate_type(prog, &var.typ)?;
|
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();
|
let typ = alias.clone().typ.inner_mut().clone();
|
||||||
prog.types.insert(alias.name.clone(), LocBox::new(stat.loc(), typ));
|
prog.types.insert(alias.name.clone(), LocBox::new(stat.loc(), typ));
|
||||||
}
|
}
|
||||||
|
Statement::Include |
|
||||||
Statement::Let { .. } => (),
|
Statement::Let { .. } => (),
|
||||||
Statement::ConstVar(var) => {
|
Statement::ConstVar(var) => {
|
||||||
prog.const_vars.insert(var.name.clone(), var.clone());
|
prog.const_vars.insert(var.name.clone(), var.clone());
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ lazy_static!(
|
||||||
("bool", (1, true)),
|
("bool", (1, true)),
|
||||||
].into();
|
].into();
|
||||||
pub static ref FUNCTIONS: HashMap<&'static str, (Vec<(&'static str, &'static str)>, &'static str)> = [
|
pub static ref FUNCTIONS: HashMap<&'static str, (Vec<(&'static str, &'static str)>, &'static str)> = [
|
||||||
("syscall", (vec![
|
("__INTERNAL_syscall", (vec![
|
||||||
("arg_count", "u8"),
|
("arg_count", "u8"),
|
||||||
("sc_num", "u8"),
|
("sc_num", "u8"),
|
||||||
("args", "&[&void]")
|
("args", "&[&void]")
|
||||||
|
|
|
||||||
2
test.mcl
2
test.mcl
|
|
@ -1,6 +1,6 @@
|
||||||
type str = [u8];
|
type str = [u8];
|
||||||
|
|
||||||
|
include "std.mcl";
|
||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
a: usize,
|
a: usize,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user