mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-22 16:08:24 +00:00
big progress
This commit is contained in:
parent
04c3fdcd07
commit
1208f25975
12
simple.ed
12
simple.ed
|
@ -1,5 +1,9 @@
|
||||||
|
fn main(x: i32) -> i32 {
|
||||||
fn main(x: i64) -> i64 {
|
let y = 0;
|
||||||
let x = 2 + 3;
|
if x == 5 {
|
||||||
return x;
|
y = 2 * x;
|
||||||
|
} else {
|
||||||
|
y = 3 * x;
|
||||||
|
}
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,10 @@ pub enum OpCode {
|
||||||
Mul,
|
Mul,
|
||||||
Div,
|
Div,
|
||||||
Rem,
|
Rem,
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
Eq,
|
||||||
|
Ne,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpCode {
|
impl OpCode {
|
||||||
|
@ -15,6 +19,10 @@ impl OpCode {
|
||||||
OpCode::Mul => "muli",
|
OpCode::Mul => "muli",
|
||||||
OpCode::Div => "divi",
|
OpCode::Div => "divi",
|
||||||
OpCode::Rem => "remi",
|
OpCode::Rem => "remi",
|
||||||
|
OpCode::And => "and",
|
||||||
|
OpCode::Or => "or",
|
||||||
|
OpCode::Eq => "eq",
|
||||||
|
OpCode::Ne => "ne",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +90,11 @@ pub enum Statement {
|
||||||
name: String,
|
name: String,
|
||||||
value: Box<Expression>,
|
value: Box<Expression>,
|
||||||
},
|
},
|
||||||
|
If {
|
||||||
|
condition: Box<Expression>,
|
||||||
|
body: Vec<Statement>,
|
||||||
|
else_body: Option<Vec<Statement>>,
|
||||||
|
},
|
||||||
Return(Option<Box<Expression>>),
|
Return(Option<Box<Expression>>),
|
||||||
Function(Function),
|
Function(Function),
|
||||||
}
|
}
|
||||||
|
|
160
src/codegen.rs
160
src/codegen.rs
|
@ -1,5 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::{HashMap, HashSet},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
todo,
|
todo,
|
||||||
};
|
};
|
||||||
|
@ -12,6 +12,7 @@ use inkwell::{
|
||||||
module::Module,
|
module::Module,
|
||||||
types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum},
|
types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum},
|
||||||
values::{BasicMetadataValueEnum, BasicValue, BasicValueEnum},
|
values::{BasicMetadataValueEnum, BasicValue, BasicValueEnum},
|
||||||
|
IntPredicate,
|
||||||
};
|
};
|
||||||
use itertools::{Either, Itertools};
|
use itertools::{Either, Itertools};
|
||||||
|
|
||||||
|
@ -40,6 +41,12 @@ pub struct CodeGen<'ctx> {
|
||||||
ast: ast::Program,
|
ast: ast::Program,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct BlockInfo<'a> {
|
||||||
|
pub blocks: Vec<BasicBlock<'a>>,
|
||||||
|
pub current_block: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'ctx> CodeGen<'ctx> {
|
impl<'ctx> CodeGen<'ctx> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
context: &'ctx Context,
|
context: &'ctx Context,
|
||||||
|
@ -70,6 +77,7 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
match &statement {
|
match &statement {
|
||||||
Statement::Variable { .. } => unreachable!(),
|
Statement::Variable { .. } => unreachable!(),
|
||||||
Statement::Return(_) => unreachable!(),
|
Statement::Return(_) => unreachable!(),
|
||||||
|
Statement::If { .. } => unreachable!(),
|
||||||
Statement::Function(function) => {
|
Statement::Function(function) => {
|
||||||
functions.push(function);
|
functions.push(function);
|
||||||
self.compile_function_signature(function)?;
|
self.compile_function_signature(function)?;
|
||||||
|
@ -130,25 +138,27 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
|
|
||||||
self.builder.position_at_end(entry_block);
|
self.builder.position_at_end(entry_block);
|
||||||
|
|
||||||
let mut variables: HashMap<String, BasicValueEnum<'ctx>> = HashMap::new();
|
let mut variables: HashMap<String, (BasicValueEnum<'ctx>, usize)> = HashMap::new();
|
||||||
|
|
||||||
for (i, param) in function.params.iter().enumerate() {
|
for (i, param) in function.params.iter().enumerate() {
|
||||||
let id = param.ident.clone();
|
let id = param.ident.clone();
|
||||||
variables.insert(
|
variables.insert(
|
||||||
id.clone(),
|
id.clone(),
|
||||||
func.get_nth_param(i.try_into().unwrap())
|
(
|
||||||
.expect("parameter"),
|
func.get_nth_param(i.try_into().unwrap())
|
||||||
|
.expect("parameter"),
|
||||||
|
0,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: check function has return?
|
|
||||||
let mut has_return = false;
|
let mut has_return = false;
|
||||||
|
|
||||||
for statement in &function.body {
|
for statement in &function.body {
|
||||||
if let Statement::Return(_) = statement {
|
if let Statement::Return(_) = statement {
|
||||||
has_return = true
|
has_return = true
|
||||||
}
|
}
|
||||||
self.compile_statement(&entry_block, statement, &mut variables)?;
|
self.compile_statement(statement, &mut variables)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !has_return {
|
if !has_return {
|
||||||
|
@ -160,29 +170,124 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
|
|
||||||
fn compile_statement(
|
fn compile_statement(
|
||||||
&self,
|
&self,
|
||||||
block: &BasicBlock,
|
|
||||||
statement: &Statement,
|
statement: &Statement,
|
||||||
variables: &mut HashMap<String, BasicValueEnum<'ctx>>,
|
// value, assignments
|
||||||
|
variables: &mut HashMap<String, (BasicValueEnum<'ctx>, usize)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match statement {
|
match statement {
|
||||||
// Variable assignment
|
// Variable assignment
|
||||||
Statement::Variable { name, value } => {
|
Statement::Variable { name, value } => {
|
||||||
let result = self
|
let result = self
|
||||||
.compile_expression(block, value, variables)?
|
.compile_expression(value, variables)?
|
||||||
.expect("should have result");
|
.expect("should have result");
|
||||||
|
|
||||||
variables.insert(name.clone(), result);
|
let accesses = if let Some(x) = variables.get(name) {
|
||||||
|
x.1 + 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
variables.insert(name.clone(), (result, accesses));
|
||||||
}
|
}
|
||||||
Statement::Return(ret) => {
|
Statement::Return(ret) => {
|
||||||
if let Some(ret) = ret {
|
if let Some(ret) = ret {
|
||||||
let result = self
|
let result = self
|
||||||
.compile_expression(block, ret, variables)?
|
.compile_expression(ret, variables)?
|
||||||
.expect("should have result");
|
.expect("should have result");
|
||||||
self.builder.build_return(Some(&result));
|
self.builder.build_return(Some(&result));
|
||||||
} else {
|
} else {
|
||||||
self.builder.build_return(None);
|
self.builder.build_return(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Statement::If {
|
||||||
|
condition,
|
||||||
|
body,
|
||||||
|
else_body,
|
||||||
|
} => {
|
||||||
|
let condition = self
|
||||||
|
.compile_expression(condition, variables)?
|
||||||
|
.expect("should produce a value");
|
||||||
|
|
||||||
|
let func = self
|
||||||
|
.builder
|
||||||
|
.get_insert_block()
|
||||||
|
.unwrap()
|
||||||
|
.get_parent()
|
||||||
|
.expect("parent should exist");
|
||||||
|
|
||||||
|
let mut if_block = self.context.append_basic_block(func, "if");
|
||||||
|
let mut else_block = self.context.append_basic_block(func, "else");
|
||||||
|
let merge_block = self.context.append_basic_block(func, "merge");
|
||||||
|
|
||||||
|
self.builder.build_conditional_branch(
|
||||||
|
condition.into_int_value(),
|
||||||
|
if_block,
|
||||||
|
if let Some(else_body) = else_body {
|
||||||
|
else_block
|
||||||
|
} else {
|
||||||
|
merge_block
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut variables_if = variables.clone();
|
||||||
|
self.builder.position_at_end(if_block);
|
||||||
|
for s in body {
|
||||||
|
self.compile_statement(s, &mut variables_if);
|
||||||
|
}
|
||||||
|
// should we set the builder at the end of the if_block again?
|
||||||
|
self.builder.build_unconditional_branch(merge_block);
|
||||||
|
if_block = self.builder.get_insert_block().unwrap(); // update for phi
|
||||||
|
|
||||||
|
let mut variables_else = variables.clone();
|
||||||
|
if let Some(else_body) = else_body {
|
||||||
|
self.builder.position_at_end(else_block);
|
||||||
|
|
||||||
|
for s in else_body {
|
||||||
|
self.compile_statement(s, &mut variables_else);
|
||||||
|
}
|
||||||
|
// should we set the builder at the end of the if_block again?
|
||||||
|
self.builder.build_unconditional_branch(merge_block);
|
||||||
|
else_block = self.builder.get_insert_block().unwrap(); // update for phi
|
||||||
|
}
|
||||||
|
|
||||||
|
self.builder.position_at_end(merge_block);
|
||||||
|
|
||||||
|
let mut processed_vars = HashMap::new();
|
||||||
|
for (name, (value, acc)) in variables_if {
|
||||||
|
if variables.contains_key(&name) {
|
||||||
|
let (old_val, old_acc) = variables.get(&name).unwrap();
|
||||||
|
if acc > *old_acc {
|
||||||
|
let phi = self
|
||||||
|
.builder
|
||||||
|
.build_phi(old_val.get_type(), &format!("{name}_phi"));
|
||||||
|
phi.add_incoming(&[(&value, if_block)]);
|
||||||
|
processed_vars.insert(name, (value, phi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if else_body.is_some() {
|
||||||
|
for (name, (value, acc)) in variables_else {
|
||||||
|
if variables.contains_key(&name) {
|
||||||
|
let (old_val, old_acc) = variables.get(&name).unwrap();
|
||||||
|
if acc > *old_acc {
|
||||||
|
if let Some((_, phi)) = processed_vars.get(&name) {
|
||||||
|
phi.add_incoming(&[(&value, else_block)]);
|
||||||
|
} else {
|
||||||
|
let phi = self
|
||||||
|
.builder
|
||||||
|
.build_phi(old_val.get_type(), &format!("{name}_phi"));
|
||||||
|
phi.add_incoming(&[(&value, else_block)]);
|
||||||
|
processed_vars.insert(name, (value, phi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (name, (_, phi)) in processed_vars {
|
||||||
|
variables.insert(name, (phi.as_basic_value(), 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
Statement::Function(_function) => unreachable!(),
|
Statement::Function(_function) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,28 +296,24 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
|
|
||||||
pub fn compile_expression(
|
pub fn compile_expression(
|
||||||
&self,
|
&self,
|
||||||
block: &BasicBlock,
|
|
||||||
expr: &Expression,
|
expr: &Expression,
|
||||||
variables: &mut HashMap<String, BasicValueEnum<'ctx>>,
|
variables: &mut HashMap<String, (BasicValueEnum<'ctx>, usize)>,
|
||||||
) -> Result<Option<BasicValueEnum<'ctx>>> {
|
) -> Result<Option<BasicValueEnum<'ctx>>> {
|
||||||
Ok(match expr {
|
Ok(match expr {
|
||||||
Expression::Variable(term) => Some(self.compile_variable(term, variables)?),
|
Expression::Variable(term) => Some(self.compile_variable(term, variables)?),
|
||||||
Expression::Literal(term) => Some(self.compile_literal(term)?),
|
Expression::Literal(term) => Some(self.compile_literal(term)?),
|
||||||
Expression::Call { function, args } => {
|
Expression::Call { function, args } => self.compile_call(function, args, variables)?,
|
||||||
self.compile_call(block, function, args, variables)?
|
|
||||||
}
|
|
||||||
Expression::BinaryOp(lhs, op, rhs) => {
|
Expression::BinaryOp(lhs, op, rhs) => {
|
||||||
Some(self.compile_binary_op(block, lhs, op, rhs, variables)?)
|
Some(self.compile_binary_op(lhs, op, rhs, variables)?)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_call(
|
pub fn compile_call(
|
||||||
&self,
|
&self,
|
||||||
block: &BasicBlock,
|
|
||||||
func_name: &str,
|
func_name: &str,
|
||||||
args: &[Box<Expression>],
|
args: &[Box<Expression>],
|
||||||
variables: &mut HashMap<String, BasicValueEnum<'ctx>>,
|
variables: &mut HashMap<String, (BasicValueEnum<'ctx>, usize)>,
|
||||||
) -> Result<Option<BasicValueEnum<'ctx>>> {
|
) -> Result<Option<BasicValueEnum<'ctx>>> {
|
||||||
let function = self.module.get_function(func_name).expect("should exist");
|
let function = self.module.get_function(func_name).expect("should exist");
|
||||||
|
|
||||||
|
@ -220,7 +321,7 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let res = self
|
let res = self
|
||||||
.compile_expression(block, arg, variables)?
|
.compile_expression(arg, variables)?
|
||||||
.expect("should have result");
|
.expect("should have result");
|
||||||
value_args.push(res.into());
|
value_args.push(res.into());
|
||||||
}
|
}
|
||||||
|
@ -238,18 +339,17 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
|
|
||||||
pub fn compile_binary_op(
|
pub fn compile_binary_op(
|
||||||
&self,
|
&self,
|
||||||
block: &BasicBlock,
|
|
||||||
lhs: &Expression,
|
lhs: &Expression,
|
||||||
op: &OpCode,
|
op: &OpCode,
|
||||||
rhs: &Expression,
|
rhs: &Expression,
|
||||||
variables: &mut HashMap<String, BasicValueEnum<'ctx>>,
|
variables: &mut HashMap<String, (BasicValueEnum<'ctx>, usize)>,
|
||||||
) -> Result<BasicValueEnum<'ctx>> {
|
) -> Result<BasicValueEnum<'ctx>> {
|
||||||
let lhs = self
|
let lhs = self
|
||||||
.compile_expression(block, lhs, variables)?
|
.compile_expression(lhs, variables)?
|
||||||
.expect("should have result")
|
.expect("should have result")
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
let rhs = self
|
let rhs = self
|
||||||
.compile_expression(block, rhs, variables)?
|
.compile_expression(rhs, variables)?
|
||||||
.expect("should have result")
|
.expect("should have result")
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|
||||||
|
@ -259,6 +359,14 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
OpCode::Mul => self.builder.build_int_mul(lhs, rhs, "mul"),
|
OpCode::Mul => self.builder.build_int_mul(lhs, rhs, "mul"),
|
||||||
OpCode::Div => self.builder.build_int_signed_div(lhs, rhs, "div"),
|
OpCode::Div => self.builder.build_int_signed_div(lhs, rhs, "div"),
|
||||||
OpCode::Rem => self.builder.build_int_signed_rem(lhs, rhs, "rem"),
|
OpCode::Rem => self.builder.build_int_signed_rem(lhs, rhs, "rem"),
|
||||||
|
OpCode::And => self.builder.build_and(lhs, rhs, "and"),
|
||||||
|
OpCode::Or => self.builder.build_or(lhs, rhs, "or"),
|
||||||
|
OpCode::Eq => self
|
||||||
|
.builder
|
||||||
|
.build_int_compare(IntPredicate::EQ, lhs, rhs, "eq"),
|
||||||
|
OpCode::Ne => self
|
||||||
|
.builder
|
||||||
|
.build_int_compare(IntPredicate::NE, lhs, rhs, "eq"),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(result.as_basic_value_enum())
|
Ok(result.as_basic_value_enum())
|
||||||
|
@ -288,9 +396,9 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
pub fn compile_variable(
|
pub fn compile_variable(
|
||||||
&self,
|
&self,
|
||||||
variable: &str,
|
variable: &str,
|
||||||
variables: &mut HashMap<String, BasicValueEnum<'ctx>>,
|
variables: &mut HashMap<String, (BasicValueEnum<'ctx>, usize)>,
|
||||||
) -> Result<BasicValueEnum<'ctx>> {
|
) -> Result<BasicValueEnum<'ctx>> {
|
||||||
let var = *variables.get(variable).expect("value");
|
let var = *variables.get(variable).expect("value");
|
||||||
Ok(var)
|
Ok(var.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ extern {
|
||||||
enum Token {
|
enum Token {
|
||||||
"let" => Token::KeywordLet,
|
"let" => Token::KeywordLet,
|
||||||
"print" => Token::KeywordPrint,
|
"print" => Token::KeywordPrint,
|
||||||
|
"struct" => Token::KeywordStruct,
|
||||||
|
"if" => Token::KeywordIf,
|
||||||
|
"else" => Token::KeywordElse,
|
||||||
"identifier" => Token::Identifier(<String>),
|
"identifier" => Token::Identifier(<String>),
|
||||||
"int" => Token::Integer(<String>),
|
"int" => Token::Integer(<String>),
|
||||||
"return" => Token::KeywordReturn,
|
"return" => Token::KeywordReturn,
|
||||||
|
@ -32,6 +35,10 @@ extern {
|
||||||
"*" => Token::OperatorMul,
|
"*" => Token::OperatorMul,
|
||||||
"/" => Token::OperatorDiv,
|
"/" => Token::OperatorDiv,
|
||||||
"%" => Token::OperatorRem,
|
"%" => Token::OperatorRem,
|
||||||
|
"&&" => Token::OperatorAnd,
|
||||||
|
"||" => Token::OperatorOr,
|
||||||
|
"==" => Token::OperatorEq,
|
||||||
|
"!=" => Token::OperatorNe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,15 +73,30 @@ Statement: ast::Statement = {
|
||||||
BasicStatement: ast::Statement = {
|
BasicStatement: ast::Statement = {
|
||||||
"let" <i:"identifier"> "=" <e:Expr> ";" => ast::Statement::Variable { name: i, value: e},
|
"let" <i:"identifier"> "=" <e:Expr> ";" => ast::Statement::Variable { name: i, value: e},
|
||||||
<i:"identifier"> "=" <e:Expr> ";" => ast::Statement::Variable { name: i, value: e},
|
<i:"identifier"> "=" <e:Expr> ";" => ast::Statement::Variable { name: i, value: e},
|
||||||
|
"if" <cond:Expr> "{" <s:Statements> "}" <e:ElseExpr?> => ast::Statement::If { condition: cond, body: s, else_body: e},
|
||||||
"return" <e:Expr?> ";" => ast::Statement::Return(e),
|
"return" <e:Expr?> ";" => ast::Statement::Return(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
ExprOp: ast::OpCode = {
|
ElseExpr: Vec<ast::Statement> = {
|
||||||
|
"else" "{" <s:Statements> "}" => s
|
||||||
|
}
|
||||||
|
|
||||||
|
Level0_Op: ast::OpCode = {
|
||||||
|
"&&" => ast::OpCode::And,
|
||||||
|
"||" => ast::OpCode::Or,
|
||||||
|
}
|
||||||
|
|
||||||
|
Level1_Op: ast::OpCode = {
|
||||||
|
"==" => ast::OpCode::Eq,
|
||||||
|
"!=" => ast::OpCode::Ne,
|
||||||
|
}
|
||||||
|
|
||||||
|
Level2_Op: ast::OpCode = {
|
||||||
"+" => ast::OpCode::Add,
|
"+" => ast::OpCode::Add,
|
||||||
"-" => ast::OpCode::Sub,
|
"-" => ast::OpCode::Sub,
|
||||||
};
|
};
|
||||||
|
|
||||||
FactorOp: ast::OpCode = {
|
Level3_Op: ast::OpCode = {
|
||||||
"*" => ast::OpCode::Mul,
|
"*" => ast::OpCode::Mul,
|
||||||
"/" => ast::OpCode::Div,
|
"/" => ast::OpCode::Div,
|
||||||
"%" => ast::OpCode::Rem,
|
"%" => ast::OpCode::Rem,
|
||||||
|
@ -85,18 +107,20 @@ Tier<Op,NextTier>: Box<ast::Expression> = {
|
||||||
NextTier
|
NextTier
|
||||||
};
|
};
|
||||||
|
|
||||||
Expr = Tier<ExprOp, Factor>;
|
Expr = Tier<Level0_Op, Expr2>;
|
||||||
Factor = Tier<FactorOp, Term>;
|
Expr2 = Tier<Level1_Op, Expr3>;
|
||||||
|
Expr3 = Tier<Level2_Op, Expr4>;
|
||||||
|
Expr4 = Tier<Level3_Op, Term>;
|
||||||
|
|
||||||
// Terms: variables, literals, calls
|
// Terms: variables, literals, calls
|
||||||
Term: Box<ast::Expression> = {
|
Term: Box<ast::Expression> = {
|
||||||
<i:"identifier"> => Box::new(ast::Expression::Variable(i)),
|
<i:"identifier"> => Box::new(ast::Expression::Variable(i)),
|
||||||
<n:Num> => Box::new(ast::Expression::Literal(n)),
|
<n:Number> => Box::new(ast::Expression::Literal(n)),
|
||||||
<i:"identifier"> "(" <values:Comma<Term>> ")" => Box::new(ast::Expression::Call { function: i, args: values}),
|
<i:"identifier"> "(" <values:Comma<Term>> ")" => Box::new(ast::Expression::Call { function: i, args: values}),
|
||||||
"(" <Term> ")"
|
"(" <Term> ")"
|
||||||
};
|
};
|
||||||
|
|
||||||
Num: ast::LiteralValue = <n:"int"> => ast::LiteralValue::Integer { bits: None, signed: true, value: n.to_string()};
|
Number: ast::LiteralValue = <n:"int"> => ast::LiteralValue::Integer { bits: None, signed: true, value: n.to_string()};
|
||||||
|
|
||||||
// Function handling
|
// Function handling
|
||||||
Param: ast::Parameter = {
|
Param: ast::Parameter = {
|
||||||
|
|
|
@ -121,6 +121,7 @@ fn main() -> Result<()> {
|
||||||
// return Ok(());
|
// return Ok(());
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
println!("{:#?}", ast);
|
||||||
let context = Context::create();
|
let context = Context::create();
|
||||||
let codegen = codegen::CodeGen::new(&context, &file_name, program, ast)?;
|
let codegen = codegen::CodeGen::new(&context, &file_name, program, ast)?;
|
||||||
codegen.compile_ast()?;
|
codegen.compile_ast()?;
|
||||||
|
|
|
@ -13,6 +13,12 @@ pub enum Token {
|
||||||
KeywordFn,
|
KeywordFn,
|
||||||
#[token("return")]
|
#[token("return")]
|
||||||
KeywordReturn,
|
KeywordReturn,
|
||||||
|
#[token("struct")]
|
||||||
|
KeywordStruct,
|
||||||
|
#[token("if")]
|
||||||
|
KeywordIf,
|
||||||
|
#[token("else")]
|
||||||
|
KeywordElse,
|
||||||
|
|
||||||
#[regex(r"_?\p{XID_Start}\p{XID_Continue}*", |lex| lex.slice().parse().ok())]
|
#[regex(r"_?\p{XID_Start}\p{XID_Continue}*", |lex| lex.slice().parse().ok())]
|
||||||
Identifier(String),
|
Identifier(String),
|
||||||
|
@ -48,6 +54,14 @@ pub enum Token {
|
||||||
OperatorDiv,
|
OperatorDiv,
|
||||||
#[token("%")]
|
#[token("%")]
|
||||||
OperatorRem,
|
OperatorRem,
|
||||||
|
#[token("&&")]
|
||||||
|
OperatorAnd,
|
||||||
|
#[token("||")]
|
||||||
|
OperatorOr,
|
||||||
|
#[token("==")]
|
||||||
|
OperatorEq,
|
||||||
|
#[token("!=")]
|
||||||
|
OperatorNe,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Token {
|
impl fmt::Display for Token {
|
||||||
|
|
Loading…
Reference in a new issue