,
}
impl Scope {
@@ -27,8 +24,8 @@ impl Scope {
functions: HashMap::new(),
name: String::default(),
function: None,
- builder: None,
fdir: None,
+ function_templates: HashMap::new(),
}
}
pub fn with_name(name: &String) -> Self {
@@ -37,8 +34,8 @@ impl Scope {
functions: HashMap::new(),
name: name.clone(),
function: None,
- builder: None,
fdir: None,
+ function_templates: HashMap::new(),
}
}
pub fn with_builder(builder: Builder) -> Self {
@@ -47,41 +44,59 @@ impl Scope {
functions: HashMap::new(),
name: String::default(),
function: None,
- builder: Some(builder),
fdir: None,
+ function_templates: HashMap::new(),
}
}
- pub fn with_builder_and_fdir(builder: Builder, fdir: PathBuf) -> Self {
+ pub fn with_fdir(fdir: P) -> Self
+ where
+ P: Into,
+ {
Self {
refs: HashMap::new(),
functions: HashMap::new(),
name: String::default(),
function: None,
- builder: Some(builder),
- fdir: Some(fdir),
+ fdir: Some(fdir.into()),
+ function_templates: HashMap::new(),
}
}
- pub fn with_function(func: (String, FunctionType), builder: Builder) -> Self {
+ pub fn with_function(func: (String, FunctionType)) -> Self {
Self {
refs: HashMap::new(),
functions: HashMap::new(),
name: func.0.clone(),
function: Some(func),
- builder: Some(builder),
fdir: None,
+ function_templates: HashMap::new(),
}
}
- pub fn func_by_name(&self, name: &String) -> Option<&FuncTyMap> {
- self.functions.get(name)
+ pub fn func_by_name(&self, name: &String) -> Option> {
+ self.functions.get(name).cloned()
+ }
+
+ pub fn get_template(&self, name: &String) -> Option {
+ self.function_templates.get(name).map(|expr| expr.clone())
+ }
+
+ pub fn add_template(&mut self, name: String, func: Expression) {
+ if self.function_templates.insert(name, func).is_some() {
+ // TODO: Error
+ panic!("ERROR");
+ }
}
pub fn add_function(&mut self, name: &String, func: Func) {
if !self.functions.contains_key(name) {
- self.functions.insert(name.clone(), vec![]);
+ self.functions.insert(name.clone(), RefCell::new(vec![]));
}
- self.functions.get_mut(name).unwrap().push(func);
+ self.functions
+ .get_mut(name)
+ .unwrap()
+ .get_mut()
+ .push(Rc::new(func));
}
pub fn find_symbol(&self, name: &String) -> Option<&Slot> {
@@ -93,20 +108,23 @@ impl Scope {
pub fn function(&self) -> Option<(String, FunctionType)> {
self.function.clone()
}
- pub fn builder(&self) -> Option<&Builder> {
- self.builder.as_ref()
- }
pub fn fdir(&self) -> Option {
self.fdir.clone()
}
- pub fn bb(&self, module: &AatbeModule, name: &String) -> Option {
- let func = self.function.as_ref()?;
+ pub fn name(&self) -> String {
+ self.name.clone()
+ }
+
+ pub fn bb(&self, module: &CompilerUnit, name: &str) -> Option {
+ let (_, ty) = self.function.as_ref()?;
Some(
- find_func(module.get_func_group(&func.0)?, &func.1)
+ find_func(module.get_func_group(&module.get_prefix().join("::"))?, &ty)
.unwrap()
- .append_basic_block(name.as_ref()),
+ .upgrade()
+ .expect("ICE")
+ .append_basic_block(name),
)
}
}
diff --git a/comp-be/src/codegen/unit/cg/assign.rs b/comp-be/src/codegen/unit/cg/assign.rs
new file mode 100644
index 0000000..33fa065
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/assign.rs
@@ -0,0 +1,20 @@
+use guard::guard;
+use parser::ast::Expression;
+
+use crate::codegen::{
+ unit::{store_value, CompilerContext},
+ ValueTypePair,
+};
+
+pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option {
+ guard!(let Expression::Assign { lval, value } = expr else { unreachable!() });
+
+ match value {
+ box Expression::RecordInit {
+ record,
+ types,
+ values,
+ } => todo!(),
+ _ => store_value(ctx, lval, value),
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/atom.rs b/comp-be/src/codegen/unit/cg/atom.rs
new file mode 100644
index 0000000..094d19d
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/atom.rs
@@ -0,0 +1,44 @@
+use parser::ast::{AtomKind, Boolean, Type};
+
+use guard::guard;
+
+use crate::{
+ codegen::{
+ builder::value,
+ expr::const_atom,
+ unit::{
+ cg::{consts, expr},
+ CompilerContext, Query, QueryResponse,
+ },
+ ValueTypePair,
+ },
+ fmt::AatbeFmt,
+};
+
+pub fn cg(atom: &AtomKind, ctx: &CompilerContext) -> Option {
+ ctx.trace(format!("Atom {}", atom.fmt()));
+ match atom {
+ AtomKind::Parenthesized(expr) => expr::cg(expr, ctx),
+ AtomKind::Unit => Some(value::unit(ctx)),
+ AtomKind::Bool(Boolean::True) => Some(value::t(ctx)),
+ AtomKind::Bool(Boolean::False) => Some(value::f(ctx)),
+ atom
+ @
+ (AtomKind::Integer(..)
+ | AtomKind::Floating(..)
+ | AtomKind::Unary(_, box AtomKind::Integer(..))) => consts::numeric::cg(atom, ctx),
+ atom @ (AtomKind::StringLiteral(..) | AtomKind::CharLiteral(..)) => const_atom(ctx, atom),
+ AtomKind::Ident(name) => {
+ guard!(let QueryResponse::Slot(slot) = ctx.query(Query::Slot(name)) else { unreachable!(); });
+ let slot = slot?;
+ match slot.var_ty().clone() {
+ ty @ Type::Newtype(_) | ty @ Type::VariantType(_) => {
+ let val: ValueTypePair = slot.into();
+ Some((*val, ty).into())
+ }
+ ty => Some((slot.load_var(ctx.llvm_builder), ty).into()),
+ }
+ }
+ _ => todo!("{:?}", atom),
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/bool.rs b/comp-be/src/codegen/unit/cg/binary/bool.rs
new file mode 100644
index 0000000..5ebc6db
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/bool.rs
@@ -0,0 +1,21 @@
+use crate::codegen::{
+ unit::{
+ cg::binary::{comp, eqne},
+ CompilerContext,
+ },
+ ValueTypePair,
+};
+use llvm_sys_wrapper::LLVMValueRef;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ctx: &CompilerContext,
+) -> Option {
+ match op.as_str() {
+ "==" | "!=" => Some(eqne::cg(lhs, op, rhs, ctx)),
+ "&&" | "||" => Some(comp::cg(lhs, op, rhs, ctx)),
+ _ => None,
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/comp.rs b/comp-be/src/codegen/unit/cg/binary/comp.rs
new file mode 100644
index 0000000..01a4389
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/comp.rs
@@ -0,0 +1,20 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::Type;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "&&" => ctx.llvm_builder.build_and(lhs, rhs),
+ "||" => ctx.llvm_builder.build_or(lhs, rhs),
+ _ => panic!("ICE codegen_eq_ne unhandled op {}", op),
+ },
+ Type::Bool,
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/eqne.rs b/comp-be/src/codegen/unit/cg/binary/eqne.rs
new file mode 100644
index 0000000..51ecc98
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/eqne.rs
@@ -0,0 +1,20 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::Type;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "==" => ctx.llvm_builder.build_icmp_eq(lhs, rhs),
+ "!=" => ctx.llvm_builder.build_icmp_ne(lhs, rhs),
+ _ => panic!("ICE codegen_eq_ne unhandled op {}", op),
+ },
+ Type::Bool,
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/float/arith.rs b/comp-be/src/codegen/unit/cg/binary/float/arith.rs
new file mode 100644
index 0000000..95be5db
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/float/arith.rs
@@ -0,0 +1,24 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::{FloatSize, Type};
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ float_size: FloatSize,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "+" => ctx.llvm_builder.build_fadd(lhs, rhs),
+ "-" => ctx.llvm_builder.build_fsub(lhs, rhs),
+ "*" => ctx.llvm_builder.build_fmul(lhs, rhs),
+ "/" => ctx.llvm_builder.build_fdiv(lhs, rhs),
+ "%" => ctx.llvm_builder.build_frem(lhs, rhs),
+ _ => panic!("ICE codegen_float_ops unhandled op {}", op),
+ },
+ Type::Float(float_size),
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/float/cmp.rs b/comp-be/src/codegen/unit/cg/binary/float/cmp.rs
new file mode 100644
index 0000000..d66f726
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/float/cmp.rs
@@ -0,0 +1,20 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::Type;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "==" => ctx.llvm_builder.build_fcmp_ueq(lhs, rhs),
+ "!=" => ctx.llvm_builder.build_fcmp_une(lhs, rhs),
+ _ => panic!("ICE codegen_eq_ne_float unhandled op {}", op),
+ },
+ Type::Bool,
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/float/eqne.rs b/comp-be/src/codegen/unit/cg/binary/float/eqne.rs
new file mode 100644
index 0000000..fdb3eed
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/float/eqne.rs
@@ -0,0 +1,22 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::Type;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "<" => ctx.llvm_builder.build_fcmp_ult(lhs, rhs),
+ ">" => ctx.llvm_builder.build_fcmp_ugt(lhs, rhs),
+ "<=" => ctx.llvm_builder.build_fcmp_ule(lhs, rhs),
+ ">=" => ctx.llvm_builder.build_fcmp_uge(lhs, rhs),
+ _ => panic!("ICE codegen_compare_float unhandled op {}", op),
+ },
+ Type::Bool,
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/float/mod.rs b/comp-be/src/codegen/unit/cg/binary/float/mod.rs
new file mode 100644
index 0000000..5f79704
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/float/mod.rs
@@ -0,0 +1,22 @@
+mod arith;
+mod cmp;
+mod eqne;
+
+use crate::codegen::{unit::CompilerContext, ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::FloatSize;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ float_size: FloatSize,
+ ctx: &CompilerContext,
+) -> Option {
+ match op.as_str() {
+ "+" | "-" | "*" | "/" | "%" => Some(arith::cg(lhs, op, rhs, float_size, ctx)),
+ ">" | "<" | ">=" | "<=" => Some(cmp::cg(lhs, op, rhs, ctx)),
+ "==" | "!=" => Some(eqne::cg(lhs, op, rhs, ctx)),
+ _ => None,
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/int/arith.rs b/comp-be/src/codegen/unit/cg/binary/int/arith.rs
new file mode 100644
index 0000000..fcd1aae
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/int/arith.rs
@@ -0,0 +1,24 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::{IntSize, Type};
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ int_size: IntSize,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "+" => ctx.llvm_builder.build_add(lhs, rhs),
+ "-" => ctx.llvm_builder.build_sub(lhs, rhs),
+ "*" => ctx.llvm_builder.build_mul(lhs, rhs),
+ "/" => ctx.llvm_builder.build_sdiv(lhs, rhs),
+ "%" => ctx.llvm_builder.build_srem(lhs, rhs),
+ _ => panic!("ICE codegen_unsigned_ops unhandled op {}", op),
+ },
+ Type::Int(int_size),
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/int/cmp.rs b/comp-be/src/codegen/unit/cg/binary/int/cmp.rs
new file mode 100644
index 0000000..b1d550d
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/int/cmp.rs
@@ -0,0 +1,22 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::Type;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "<" => ctx.llvm_builder.build_icmp_slt(lhs, rhs),
+ ">" => ctx.llvm_builder.build_icmp_sgt(lhs, rhs),
+ "<=" => ctx.llvm_builder.build_icmp_sle(lhs, rhs),
+ ">=" => ctx.llvm_builder.build_icmp_sge(lhs, rhs),
+ _ => panic!("ICE codegen_compare_signed unhandled op {}", op),
+ },
+ Type::Bool,
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/int/mod.rs b/comp-be/src/codegen/unit/cg/binary/int/mod.rs
new file mode 100644
index 0000000..d061784
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/int/mod.rs
@@ -0,0 +1,24 @@
+mod arith;
+mod cmp;
+
+use crate::codegen::{
+ unit::{cg::binary::eqne, CompilerContext},
+ ValueTypePair,
+};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::IntSize;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ int_size: IntSize,
+ ctx: &CompilerContext,
+) -> Option {
+ match op.as_str() {
+ "+" | "-" | "*" | "/" | "%" => Some(arith::cg(lhs, op, rhs, int_size, ctx)),
+ ">" | "<" | ">=" | "<=" => Some(cmp::cg(lhs, op, rhs, ctx)),
+ "==" | "!=" => Some(eqne::cg(lhs, op, rhs, ctx)),
+ _ => None,
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/mod.rs b/comp-be/src/codegen/unit/cg/binary/mod.rs
new file mode 100644
index 0000000..ceeef7a
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/mod.rs
@@ -0,0 +1,88 @@
+mod bool;
+mod comp;
+mod eqne;
+mod float;
+mod int;
+mod uint;
+
+use parser::ast::{Expression, IntSize, Type};
+
+use guard::guard;
+
+use crate::{
+ codegen::{
+ unit::{cg::expr, CompilerContext},
+ CompileError, GenRes,
+ },
+ fmt::AatbeFmt,
+};
+
+pub fn cg(expr: &Expression, ctx: &CompilerContext) -> GenRes {
+ guard!(let Expression::Binary(box lh, op, box rh) = expr else { unreachable!() });
+
+ let lhs = expr::cg(lh, ctx).ok_or(CompileError::Handled)?;
+ let rhs = expr::cg(rh, ctx).ok_or(CompileError::Handled)?;
+
+ match (lhs.prim(), rhs.prim()) {
+ (Type::Bool, Type::Bool) => {
+ ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt()));
+ match bool::cg(*lhs, op, *rhs, ctx) {
+ Some(res) => Ok(res),
+ None => Err(CompileError::OpMismatch {
+ op: op.clone(),
+ types: (lhs.prim().fmt(), rhs.prim().fmt()),
+ values: (lh.fmt(), rh.fmt()),
+ }),
+ }
+ }
+ (Type::Char, Type::Char) => {
+ ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt()));
+ match uint::cg(*lhs, op, *rhs, IntSize::Bits8, ctx) {
+ Some(res) => Ok(res),
+ None => Err(CompileError::OpMismatch {
+ op: op.clone(),
+ types: (lhs.prim().fmt(), rhs.prim().fmt()),
+ values: (lh.fmt(), rh.fmt()),
+ }),
+ }
+ }
+ (Type::UInt(lsz), Type::UInt(rsz)) if lsz == rsz => {
+ ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt()));
+ match uint::cg(*lhs, op, *rhs, lsz.clone(), ctx) {
+ Some(res) => Ok(res),
+ None => Err(CompileError::OpMismatch {
+ op: op.clone(),
+ types: (lhs.prim().fmt(), rhs.prim().fmt()),
+ values: (lh.fmt(), rh.fmt()),
+ }),
+ }
+ }
+ (Type::Int(lsz), Type::Int(rsz)) if lsz == rsz => {
+ ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt()));
+ match int::cg(*lhs, op, *rhs, lsz.clone(), ctx) {
+ Some(res) => Ok(res),
+ None => Err(CompileError::OpMismatch {
+ op: op.clone(),
+ types: (lhs.prim().fmt(), rhs.prim().fmt()),
+ values: (lh.fmt(), rh.fmt()),
+ }),
+ }
+ }
+ (Type::Float(lsz), Type::Float(rsz)) if lsz == rsz => {
+ ctx.trace(format!("Binary {} {} {}", lh.fmt(), op, rh.fmt()));
+ match float::cg(*lhs, op, *rhs, lsz.clone(), ctx) {
+ Some(res) => Ok(res),
+ None => Err(CompileError::OpMismatch {
+ op: op.clone(),
+ types: (lhs.prim().fmt(), rhs.prim().fmt()),
+ values: (lh.fmt(), rh.fmt()),
+ }),
+ }
+ }
+ _ => Err(CompileError::BinaryMismatch {
+ op: op.clone(),
+ types: (lhs.prim().fmt(), rhs.prim().fmt()),
+ values: (lh.fmt(), rh.fmt()),
+ }),
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/uint/arith.rs b/comp-be/src/codegen/unit/cg/binary/uint/arith.rs
new file mode 100644
index 0000000..1873091
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/uint/arith.rs
@@ -0,0 +1,24 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::{IntSize, Type};
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ty: IntSize,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "+" => ctx.llvm_builder.build_add(lhs, rhs),
+ "-" => ctx.llvm_builder.build_sub(lhs, rhs),
+ "*" => ctx.llvm_builder.build_mul(lhs, rhs),
+ "/" => ctx.llvm_builder.build_udiv(lhs, rhs),
+ "%" => ctx.llvm_builder.build_urem(lhs, rhs),
+ _ => panic!("ICE codegen_unsigned_ops unhandled op {}", op),
+ },
+ Type::UInt(ty),
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/uint/cmp.rs b/comp-be/src/codegen/unit/cg/binary/uint/cmp.rs
new file mode 100644
index 0000000..c03bd83
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/uint/cmp.rs
@@ -0,0 +1,22 @@
+use crate::{codegen::unit::CompilerContext, codegen::ValueTypePair};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::Type;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ctx: &CompilerContext,
+) -> ValueTypePair {
+ (
+ match op.as_str() {
+ "<" => ctx.llvm_builder.build_icmp_ult(lhs, rhs),
+ ">" => ctx.llvm_builder.build_icmp_ugt(lhs, rhs),
+ "<=" => ctx.llvm_builder.build_icmp_ule(lhs, rhs),
+ ">=" => ctx.llvm_builder.build_icmp_uge(lhs, rhs),
+ _ => panic!("ICE codegen_compare_unsigned unhandled op {}", op),
+ },
+ Type::Bool,
+ )
+ .into()
+}
diff --git a/comp-be/src/codegen/unit/cg/binary/uint/mod.rs b/comp-be/src/codegen/unit/cg/binary/uint/mod.rs
new file mode 100644
index 0000000..a127a3a
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/binary/uint/mod.rs
@@ -0,0 +1,24 @@
+mod arith;
+mod cmp;
+
+use crate::codegen::{
+ unit::{cg::binary::eqne, CompilerContext},
+ ValueTypePair,
+};
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::IntSize;
+
+pub fn cg(
+ lhs: LLVMValueRef,
+ op: &String,
+ rhs: LLVMValueRef,
+ ty: IntSize,
+ ctx: &CompilerContext,
+) -> Option {
+ match op.as_str() {
+ "+" | "-" | "*" | "/" | "%" => Some(arith::cg(lhs, op, rhs, ty, ctx)),
+ ">" | "<" | ">=" | "<=" => Some(cmp::cg(lhs, op, rhs, ctx)),
+ "==" | "!=" => Some(eqne::cg(lhs, op, rhs, ctx)),
+ _ => None,
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/call.rs b/comp-be/src/codegen/unit/cg/call.rs
new file mode 100644
index 0000000..33abc3e
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/call.rs
@@ -0,0 +1,100 @@
+use std::borrow::Borrow;
+
+use parser::ast::{AtomKind, Expression, IdentPath, Type};
+
+use llvm_sys_wrapper::LLVMValueRef;
+
+use crate::{
+ codegen::{
+ builder::base,
+ unit::{cg::expr, function::find_function, CompilerContext, Query, QueryResponse},
+ ValueTypePair,
+ },
+ fmt::AatbeFmt,
+ prefix,
+};
+
+use guard::guard;
+use log::*;
+
+pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option {
+ guard!(let Expression::Call {
+ name,
+ types: _,
+ args,
+ } = expr else { unreachable!() });
+
+ ctx.trace(format!("Call {}", AatbeFmt::fmt(expr)));
+
+ guard!(let Some((call_types, mut call_args)) = compute_arguments(args, ctx) else {
+ trace!("Got error");
+ return None
+ });
+
+ let prefix = |path: &IdentPath| -> Vec {
+ match path {
+ IdentPath::Local(name) => prefix!(call ctx, name.clone()),
+ IdentPath::Module(name) => prefix!(call module ctx, name.clone()),
+ IdentPath::Root(name) => name.clone(),
+ }
+ };
+
+ find_function(
+ match ctx.query(Query::FunctionGroup(prefix(name).join("::"))) {
+ QueryResponse::FunctionGroup(Some(group)) => group,
+ QueryResponse::FunctionGroup(None) => todo!("no function found"),
+ _ => unreachable!(),
+ },
+ &call_types,
+ )
+ .map(|func| base::call(ctx, func.upgrade().expect("ICE").borrow(), &mut call_args))
+}
+
+fn compute_arguments(
+ args: &Vec,
+ ctx: &CompilerContext,
+) -> Option<(Vec, Vec)> {
+ let mut call_types = vec![];
+ let mut error = false;
+
+ let call_args = args
+ .iter()
+ .filter_map(|arg| match arg {
+ Expression::Atom(AtomKind::SymbolLiteral(sym)) => {
+ call_types.push(Type::Symbol(sym.clone()));
+ None
+ }
+ Expression::Atom(AtomKind::Unit) => {
+ call_types.push(Type::Unit);
+ None
+ }
+ _ => {
+ let expr = expr::cg(&arg, ctx);
+
+ if expr.is_none() {
+ error = true;
+
+ None
+ } else {
+ expr.map_or(None, |arg| match arg.prim().clone() {
+ ref ty @ Type::VariantType(ref _name) => todo!("{:?}", ty),
+ ref ty @ Type::Array { .. } => todo!("{:?}", ty),
+ ref ty @ Type::Ref(box Type::Array { .. }) => {
+ todo!("{:?}", ty)
+ }
+ ref ty @ _ => {
+ call_types.push(ty.clone());
+ Some(*arg)
+ }
+ })
+ }
+ }
+ })
+ .collect::>();
+
+ if error {
+ None
+ } else {
+ Some((call_types, call_args))
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/conditional/ifelse.rs b/comp-be/src/codegen/unit/cg/conditional/ifelse.rs
new file mode 100644
index 0000000..01739b1
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/conditional/ifelse.rs
@@ -0,0 +1,172 @@
+use crate::{
+ codegen::{
+ builder::{base, branch},
+ unit::{cg::expr, CompilerContext, Message},
+ ValueTypePair,
+ },
+ fmt::AatbeFmt,
+ ty::LLVMTyInCtx,
+};
+use llvm_sys_wrapper::{LLVMBasicBlockRef, Phi};
+use parser::ast::{Expression, Type};
+
+use guard::guard;
+
+pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option {
+ guard!(let Expression::If {
+ cond_expr,
+ then_expr,
+ elseif_exprs,
+ else_expr
+ } = expr else { unreachable!() });
+
+ let then_bb = ctx.basic_block("then");
+ let elseif_bbs = elseif_exprs
+ .iter()
+ .map(|e| {
+ (
+ (
+ ctx.basic_block("elseif_cond"),
+ ctx.basic_block("elseif_body"),
+ ),
+ e,
+ )
+ })
+ .collect::>();
+ let else_bb = else_expr.as_ref().map(|_| ctx.basic_block("else"));
+ let end_bb = ctx.basic_block("if_end");
+
+ ctx.dispatch(Message::EnterIfScope(cond_expr.fmt()));
+ let cond = expr::cg(cond_expr, ctx)?;
+
+ if *cond.prim().inner() != Type::Bool {
+ /*
+ self.add_error(CompileError::ExpectedType {
+ expected_ty: Type::Bool.fmt(),
+ found_ty: cond.prim().fmt(),
+ value: cond_expr.fmt(),
+ }); */
+ todo!("NOT A BOOL");
+ }
+
+ let next_bb = |i: usize| -> LLVMBasicBlockRef {
+ elseif_bbs
+ .get(i)
+ .map(|e| e.0 .0)
+ .unwrap_or(else_bb.unwrap_or(end_bb))
+ };
+
+ branch::cond_branch(ctx, *cond, then_bb, next_bb(0));
+
+ base::pos_at_end(ctx, then_bb);
+ let then_val = expr::cg(then_expr, ctx)?;
+
+ ctx.dispatch(Message::ExitScope);
+
+ let elseif_vals = elseif_bbs
+ .iter()
+ .enumerate()
+ .map(|(i, ((bb_cond, bb_body), (cond, expr)))| {
+ ctx.dispatch(Message::EnterElseIfScope(cond.fmt()));
+ base::pos_at_end(ctx, *bb_cond);
+
+ let cond = expr::cg(cond, ctx)?;
+
+ if *cond.prim().inner() != Type::Bool {
+ /*
+ self.add_error(CompileError::ExpectedType {
+ expected_ty: Type::Bool.fmt(),
+ found_ty: cond.prim().fmt(),
+ value: cond_expr.fmt(),
+ }); */
+ todo!("NOT A BOOL");
+ }
+
+ branch::cond_branch(ctx, *cond, *bb_body, next_bb(i + 1));
+
+ base::pos_at_end(ctx, *bb_body);
+ let val = expr::cg(expr, ctx);
+ branch::branch(ctx, end_bb);
+ ctx.dispatch(Message::ExitScope);
+
+ val
+ })
+ .collect::>();
+
+ base::pos_at_end(ctx, then_bb);
+
+ let else_val = else_bb
+ .map(|bb| {
+ ctx.dispatch(Message::EnterElseScope);
+ branch::branch(ctx, end_bb);
+ base::pos_at_end(ctx, bb);
+
+ let res = else_expr.as_ref().and_then(|expr| expr::cg(&expr, ctx));
+ ctx.dispatch(Message::ExitScope);
+ res
+ })
+ .flatten();
+
+ branch::branch(ctx, end_bb);
+
+ base::pos_at_end(ctx, end_bb);
+
+ let ty = then_val.prim().inner().clone();
+ let mut values = vec![*then_val];
+ let mut blocks = vec![then_bb];
+
+ // Else If type failed to compile
+ if elseif_vals.len() != 0 && elseif_vals.iter().any(|v| v.is_none()) {
+ // TODO: Error
+ return None;
+ } else {
+ let velseif = elseif_vals
+ .iter()
+ .map(|e| e.as_ref().unwrap())
+ .collect::>();
+
+ // Else If types do not match if type
+ if !velseif
+ .iter()
+ .fold(true, |a, b| a && b.prim().inner() == &ty)
+ {
+ // TODO: Error
+ return None;
+ } else {
+ for (i, val) in velseif.iter().enumerate() {
+ values.push(***val);
+ blocks.push(elseif_bbs[i].0 .1);
+ }
+ }
+ }
+
+ // Else type does not match if type
+ if else_val
+ .as_ref()
+ .map(|v| v.prim().inner().clone())
+ .unwrap_or(ty.clone())
+ != ty
+ {
+ // TODO: Error
+ return None;
+ } else if let Some(velse) = else_val {
+ values.push(*velse);
+ blocks.push(else_bb.unwrap());
+ }
+
+ if ty == Type::Unit {
+ return None;
+ }
+
+ match values.len() {
+ 0 => None,
+ 1 => Some(then_val),
+ _ => {
+ let phi = Phi::new(ctx.llvm_builder.as_ref(), ty.llvm_ty_in_ctx(ctx), "");
+
+ phi.add_incomings(&mut values, &mut blocks);
+
+ Some((phi.as_ref(), ty).into())
+ }
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/conditional/loops.rs b/comp-be/src/codegen/unit/cg/conditional/loops.rs
new file mode 100644
index 0000000..1b89df0
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/conditional/loops.rs
@@ -0,0 +1,48 @@
+use parser::ast::{Expression, LoopType, Type};
+
+use guard::guard;
+
+use crate::codegen::{
+ builder::{base, branch},
+ unit::{cg::expr, CompilerContext},
+ ValueTypePair,
+};
+
+pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option {
+ guard!(let Expression::Loop {
+ loop_type,
+ cond_expr,
+ body
+ } = expr else { unreachable!() });
+
+ let cond_bb = ctx.basic_block("while_cond");
+ let body_bb = ctx.basic_block("while_body");
+
+ branch::branch(ctx, cond_bb);
+ base::pos_at_end(ctx, cond_bb);
+ let cond = expr::cg(cond_expr, ctx)?;
+
+ if *cond.prim().inner() != Type::Bool {
+ // TODO: Error
+ /*self.add_error(CompileError::ExpectedType {
+ expected_ty: Type::Bool.fmt(),
+ found_ty: cond.prim().fmt(),
+ value: cond_expr.fmt(),
+ });*/
+ };
+
+ base::pos_at_end(ctx, body_bb);
+ expr::cg(body, ctx);
+ branch::branch(ctx, cond_bb);
+
+ base::pos_at_end(ctx, cond_bb);
+ let end_bb = ctx.basic_block("while_end");
+ match loop_type {
+ LoopType::While => branch::cond_branch(ctx, *cond, body_bb, end_bb),
+ LoopType::Until => branch::cond_branch(ctx, *cond, end_bb, body_bb),
+ };
+
+ base::pos_at_end(ctx, end_bb);
+
+ None
+}
diff --git a/comp-be/src/codegen/unit/cg/conditional/mod.rs b/comp-be/src/codegen/unit/cg/conditional/mod.rs
new file mode 100644
index 0000000..0ae47bc
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/conditional/mod.rs
@@ -0,0 +1,2 @@
+pub mod ifelse;
+pub mod loops;
diff --git a/comp-be/src/codegen/unit/cg/consts/mod.rs b/comp-be/src/codegen/unit/cg/consts/mod.rs
new file mode 100644
index 0000000..4375cad
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/consts/mod.rs
@@ -0,0 +1 @@
+pub mod numeric;
diff --git a/comp-be/src/codegen/unit/cg/consts/numeric.rs b/comp-be/src/codegen/unit/cg/consts/numeric.rs
new file mode 100644
index 0000000..934e00a
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/consts/numeric.rs
@@ -0,0 +1,28 @@
+use parser::ast::{AtomKind, Type};
+
+use crate::codegen::{builder::value, unit::CompilerContext, ValueTypePair};
+
+pub fn cg(atom: &AtomKind, ctx: &CompilerContext) -> Option {
+ match atom {
+ AtomKind::Integer(val, Type::Int(size)) => {
+ Some(value::sint(ctx, size.clone(), *val))
+ }
+ AtomKind::Integer(val, Type::UInt(size)) => {
+ Some(value::uint(ctx, size.clone(), *val))
+ }
+ AtomKind::Floating(val, Type::Float(size)) => {
+ Some(value::floating(ctx, size.clone(), *val))
+ }
+ AtomKind::Unary(op, box AtomKind::Integer(val, Type::Int(size)))
+ if op == &String::from("-") =>
+ {
+ Some(value::sint(ctx, size.clone(), (-(*val as i64)) as u64))
+ }
+ AtomKind::Unary(op, box AtomKind::Integer(val, Type::UInt(size)))
+ if op == &String::from("-") =>
+ {
+ Some(value::uint(ctx, size.clone(), (-(*val as i64)) as u64))
+ }
+ _ => panic!("ICE Atom {:?}", atom),
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/decl.rs b/comp-be/src/codegen/unit/cg/decl.rs
new file mode 100644
index 0000000..36bba7a
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/decl.rs
@@ -0,0 +1,40 @@
+use parser::ast::{Expression, Type};
+
+use guard::guard;
+
+use crate::codegen::{
+ unit::{alloc_variable, CompilerContext, Query, QueryResponse},
+ ValueTypePair,
+};
+
+pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option {
+ match expr {
+ Expression::Decl {
+ ty: Type::NamedType { name, ty: Some(ty) },
+ value: _,
+ exterior_bind: _,
+ } => {
+ alloc_variable(expr, ctx);
+
+ guard!(let QueryResponse::Slot(slot) = ctx.query(Query::Slot(name)) else { unreachable!() });
+ let slot = slot?;
+ Some((slot.into(), *ty.clone()).into())
+ }
+ Expression::Decl {
+ ty: Type::NamedType { name, ty: None },
+ value,
+ exterior_bind: _,
+ } => {
+ if value.is_none() {
+ todo!("ERROR")
+ }
+
+ alloc_variable(expr, ctx).and_then(|ty| {
+ guard!(let QueryResponse::Slot(slot) = ctx.query(Query::Slot(name)) else { unreachable!() });
+ let slot = slot?;
+ Some((slot.into(), ty).into())
+ })
+ }
+ _ => unreachable!(),
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/expr.rs b/comp-be/src/codegen/unit/cg/expr.rs
new file mode 100644
index 0000000..36006bb
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/expr.rs
@@ -0,0 +1,44 @@
+use parser::ast::{Expression, FunctionType};
+
+use crate::codegen::{
+ unit::{
+ cg::{assign, atom, binary, call, conditional, decl},
+ declare_and_compile_function, CompilerContext, Message,
+ },
+ ValueTypePair,
+};
+
+pub fn cg(expr: &Expression, ctx: &CompilerContext) -> Option {
+ match expr {
+ Expression::Assign { .. } => assign::cg(expr, ctx),
+ Expression::Decl { .. } => decl::cg(expr, ctx),
+ Expression::Loop { .. } => conditional::loops::cg(expr, ctx),
+ Expression::If { .. } => conditional::ifelse::cg(expr, ctx),
+ Expression::Binary(..) => Some(binary::cg(expr, ctx).ok().expect("todo")),
+ Expression::Call { .. } => call::cg(expr, ctx),
+ Expression::Atom(atom) => atom::cg(atom, ctx),
+ Expression::Function { ty, type_names, .. } if type_names.len() == 0 => match ty {
+ FunctionType {
+ ret_ty: _,
+ params: _,
+ ext: true,
+ } => None,
+ _ => declare_and_compile_function(ctx, expr),
+ },
+ Expression::Function { .. } => None,
+ Expression::Block(body) if body.len() == 0 => None,
+ Expression::Block(body) => {
+ ctx.dispatch(Message::EnterAnonymousScope);
+
+ let ret = body
+ .iter()
+ .fold(None, |_, expr| Some(cg(expr, ctx)))
+ .unwrap();
+
+ ctx.dispatch(Message::ExitScope);
+
+ ret
+ }
+ _ => todo!("{:?}", expr),
+ }
+}
diff --git a/comp-be/src/codegen/unit/cg/mod.rs b/comp-be/src/codegen/unit/cg/mod.rs
new file mode 100644
index 0000000..0ea5b69
--- /dev/null
+++ b/comp-be/src/codegen/unit/cg/mod.rs
@@ -0,0 +1,27 @@
+use llvm_sys_wrapper::LLVMValueRef;
+use parser::ast::AST;
+
+use super::{CompilerContext, Message};
+
+pub mod assign;
+pub mod atom;
+pub mod binary;
+pub mod call;
+pub mod conditional;
+pub mod consts;
+pub mod decl;
+pub mod expr;
+
+pub fn cg(ast: &AST, ctx: &CompilerContext) -> Option {
+ match ast {
+ AST::Expr(expr) => expr::cg(expr, ctx).map(|e| *e),
+ AST::File(nodes) => nodes.iter().fold(None, |_, n| cg(n, ctx)),
+ AST::Module(name, ast) => {
+ ctx.dispatch(Message::RestoreModuleScope(name.clone()));
+ let ret = cg(ast, ctx);
+ ctx.dispatch(Message::ExitScope);
+ ret
+ }
+ _ => todo!("{:?}", ast),
+ }
+}
diff --git a/comp-be/src/codegen/unit/compiler.rs b/comp-be/src/codegen/unit/compiler.rs
new file mode 100644
index 0000000..c27ffba
--- /dev/null
+++ b/comp-be/src/codegen/unit/compiler.rs
@@ -0,0 +1,583 @@
+use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Weak};
+
+use llvm_sys_wrapper::{Builder, Context, LLVMBasicBlockRef, LLVMValueRef, Module};
+use parser::ast::{Expression, FunctionType, AST};
+
+use crate::{
+ codegen::{
+ comp_unit::CompilationUnit,
+ unit::{cg, decl, function::find_func, generic},
+ Scope, ValueTypePair,
+ },
+ fmt::AatbeFmt,
+ ty::TypeContext,
+};
+
+use super::{
+ function::{Func, FuncTyMap},
+ Slot,
+};
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum FunctionVisibility {
+ Local,
+ Public,
+}
+
+pub enum Message {
+ PushFunctionTemplate(String, Expression),
+ PushInScope(String, Slot),
+ DeclareFunction(String, Func, FunctionVisibility),
+ EnterFunctionScope((String, FunctionType)),
+ EnterModuleScope(String),
+ ExitModuleScope(String),
+ RestoreModuleScope(String),
+ EnterIfScope(String),
+ EnterElseIfScope(String),
+ EnterElseScope,
+ EnterAnonymousScope,
+ ExitScope,
+}
+
+impl std::fmt::Debug for Message {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ match &self {
+ Message::PushFunctionTemplate(name, expr) => {
+ f.debug_tuple("PushFunctionTemplate").field(name).finish()
+ }
+ Message::PushInScope(name, slot) => f
+ .debug_tuple("PushInScope")
+ .field(name)
+ .field(slot)
+ .finish(),
+ Message::DeclareFunction(name, ty, vis) => f
+ .debug_tuple("DeclareFunction")
+ .field(name)
+ .field(&AatbeFmt::fmt(ty))
+ .field(vis)
+ .finish(),
+ Message::EnterFunctionScope(func) => f
+ .debug_tuple("EnterFunctionScope")
+ .field(&func.0)
+ .field(&AatbeFmt::fmt(&func.1))
+ .finish(),
+ Message::EnterModuleScope(name) => {
+ f.debug_tuple("EnterModuleScope").field(&name).finish()
+ }
+ Message::ExitModuleScope(name) => {
+ f.debug_tuple("ExitModuleScope").field(&name).finish()
+ }
+ Message::RestoreModuleScope(name) => {
+ f.debug_tuple("RestoreModuleScope").field(&name).finish()
+ }
+ Message::EnterIfScope(cond) => f.debug_tuple("EnterIfScope").field(cond).finish(),
+ Message::EnterElseIfScope(cond) => {
+ f.debug_tuple("EnterElseIfScope").field(cond).finish()
+ }
+ Message::EnterElseScope => write!(f, "EnterElseScope"),
+ Message::EnterAnonymousScope => write!(f, "EnterAnonymousScope"),
+ Message::ExitScope => write!(f, "ExitScope"),
+ }
+ }
+}
+
+pub enum Query<'cmd> {
+ Slot(&'cmd String),
+ Function((String, &'cmd FunctionType)),
+ FunctionGroup(String),
+ Prefix,
+}
+
+impl std::fmt::Debug for Query<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Query::Slot(name) => f.debug_tuple("Slot").field(name).finish(),
+ Query::Function(func) => f
+ .debug_tuple("Function")
+ .field(&func.0)
+ .field(&AatbeFmt::fmt(func.1))
+ .finish(),
+ Query::FunctionGroup(name) => f.debug_tuple("FunctionGroup").field(name).finish(),
+ Query::Prefix => write!(f, "Prefix"),
+ }
+ }
+}
+
+pub enum QueryResponse {
+ Slot(Option),
+ Function(Option>),
+ FunctionGroup(Option>),
+ Prefix(Vec),
+}
+
+impl std::fmt::Debug for QueryResponse {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ QueryResponse::Slot(slot) => f.debug_tuple("Slot").field(slot).finish(),
+ QueryResponse::Function(ref func) => f
+ .debug_tuple("Function")
+ .field(
+ &func
+ .as_ref()
+ .map(|f| AatbeFmt::fmt(f.upgrade().expect("ICE").as_ref())),
+ )
+ .finish(),
+ QueryResponse::FunctionGroup(group) => f
+ .debug_tuple("FunctionGroup")
+ .field(&format_args!(
+ "{}",
+ match &group {
+ None => String::from("[]"),
+ Some(gr) => format!("{:?}", gr.borrow().iter().collect::>()),
+ }
+ ))
+ .finish(),
+ QueryResponse::Prefix(prefix) => f
+ .debug_tuple("Prefix")
+ .field(&format_args!("{}", prefix.join("::")))
+ .finish(),
+ }
+ }
+}
+
+pub struct CompilerContext<'ctx> {
+ pub path: PathBuf,
+ pub llvm_context: &'ctx Context,
+ pub llvm_module: &'ctx Module,
+ pub llvm_builder: &'ctx Builder,
+ dispatch: &'ctx dyn Fn(Message) -> (),
+ query: &'ctx dyn Fn(Query) -> QueryResponse,
+ trace: &'ctx dyn Fn(String) -> (),
+ basic_block: &'ctx dyn Fn(&str) -> LLVMBasicBlockRef,
+}
+
+impl<'ctx> CompilerContext<'ctx> {
+ pub fn new(
+ path: P,
+ llvm_context: &'ctx Context,
+ llvm_module: &'ctx Module,
+ llvm_builder: &'ctx Builder,
+ dispatch: &'ctx dyn Fn(Message) -> (),
+ query: &'ctx dyn Fn(Query) -> QueryResponse,
+ trace: &'ctx dyn Fn(String) -> (),
+ basic_block: &'ctx dyn Fn(&str) -> LLVMBasicBlockRef,
+ ) -> Self
+ where
+ P: Into,
+ {
+ Self {
+ path: path.into(),
+ llvm_context,
+ llvm_module,
+ llvm_builder,
+ dispatch,
+ query,
+ trace,
+ basic_block,
+ }
+ }
+
+ fn with_builder(&'ctx self, builder: &'ctx Builder) -> Self {
+ Self {
+ path: self.path.clone(),
+ llvm_context: self.llvm_context,
+ llvm_module: self.llvm_module,
+ llvm_builder: builder,
+ dispatch: self.dispatch,
+ query: self.query,
+ trace: self.trace,
+ basic_block: self.basic_block,
+ }
+ }
+
+ pub fn basic_block(&self, name: &str) -> LLVMBasicBlockRef {
+ (self.basic_block)(name)
+ }
+
+ pub fn trace(&self, message: String) {
+ (self.trace)(message)
+ }
+
+ pub fn dispatch(&self, message: Message) {
+ (self.dispatch)(message)
+ }
+
+ pub fn query(&self, query: Query) -> QueryResponse {
+ (self.query)(query)
+ }
+
+ pub fn in_function_scope(&self, func: (String, FunctionType), f: F) -> Option
+ where
+ F: FnOnce(CompilerContext) -> Option,
+ {
+ self.dispatch(Message::EnterFunctionScope(func));
+ let builder = Builder::new_in_context(self.llvm_context.as_ref());
+ let ctx = self.with_builder(&builder);
+ let res = f(ctx);
+ self.dispatch(Message::ExitScope);
+ res
+ }
+}
+
+pub struct CompilerUnit<'ctx> {
+ modules: HashMap>,
+ _typectx: TypeContext,
+ llvm_context: &'ctx Context,
+ llvm_module: &'ctx Module,
+ scope_stack: RefCell>,
+ module_scopes: RefCell>,
+ path: PathBuf,
+ ident: RefCell,
+ generic_processor: RefCell,
+}
+
+impl<'ctx> CompilerUnit<'ctx> {
+ pub fn new(path: P, llvm_context: &'ctx Context, llvm_module: &'ctx Module) -> Self
+ where
+ P: Into,
+ {
+ Self {
+ path: path.into(),
+ llvm_context,
+ llvm_module,
+ modules: HashMap::new(),
+ _typectx: TypeContext::new(),
+ scope_stack: RefCell::new(vec![]),
+ module_scopes: RefCell::new(HashMap::new()),
+ ident: RefCell::new(0),
+ generic_processor: RefCell::new(generic::Processor::new()),
+ }
+ }
+
+ pub fn in_root_scope(&self, f: F)
+ where
+ F: FnOnce(&Self),
+ {
+ self.enter_root_scope();
+ f(self);
+ println!("└── Exit Root Scope");
+ self.exit_scope();
+ }
+
+ fn enter_root_scope(&self) {
+ println!("Enter Root Scope");
+ self.scope_stack
+ .borrow_mut()
+ .push(Scope::with_fdir(self.path.clone()));
+ }
+
+ fn enter_anonymous_scope(&self) {
+ self.scope_stack.borrow_mut().push(Scope::new());
+ }
+
+ fn enter_function_scope(&self, func: (String, FunctionType)) {
+ self.scope_stack
+ .borrow_mut()
+ .push(Scope::with_function((func.0, func.1)));
+ }
+
+ fn enter_module_scope(&self, name: String) {
+ self.scope_stack.borrow_mut().push(Scope::with_name(&name));
+ }
+
+ fn exit_module_scope(&self, name: String) {
+ let scope = self
+ .scope_stack
+ .borrow_mut()
+ .pop()
+ .expect("ICE Scope stack broke");
+ self.module_scopes.borrow_mut().insert(name, scope);
+ }
+
+ fn restore_module_scope(&self, name: String) {
+ let scope = self
+ .module_scopes
+ .borrow_mut()
+ .remove(&name)
+ .expect("ICE Scope stack broke");
+ self.scope_stack.borrow_mut().push(scope);
+ }
+
+ pub fn push_in_scope(&self, name: &String, unit: Slot) {
+ self.scope_stack
+ .borrow_mut()
+ .last_mut()
+ .expect("Compiler broke. Scope stack is corrupted.")
+ .add_symbol(name, unit);
+ }
+
+ pub fn push_function_template(&self, name: String, func: Expression) {
+ self.scope_stack
+ .borrow_mut()
+ .last_mut()
+ .expect("Compiler broke. Scope stack is corrupted.")
+ .add_template(name, func);
+ }
+
+ pub fn get_from_scope(&self, name: &String) -> Option {
+ for scope in self.scope_stack.borrow().iter().rev() {
+ if let Some(sym) = scope.find_symbol(name) {
+ return Some(sym.clone());
+ }
+ }
+
+ None
+ }
+
+ pub fn get_slot(&self, name: &String) -> Option {
+ if let Some(slot @ (Slot::Variable { .. } | Slot::FunctionArgument(..))) =
+ self.get_from_scope(name)
+ {
+ Some(slot)
+ } else {
+ None
+ }
+ }
+
+ fn exit_scope(&self) {
+ self.scope_stack
+ .borrow_mut()
+ .pop()
+ .expect("ICE Scope Stack Broke");
+ }
+
+ fn dispatch(&self, message: Message) {
+ print!("{}", "│ ".repeat(*self.ident.borrow()));
+ println!("├── {:?}", message);
+ match message {
+ Message::PushFunctionTemplate(name, func) => {
+ self.push_function_template(name, func);
+ }
+ Message::PushInScope(ref name, unit) => {
+ self.push_in_scope(name, unit.clone());
+ }
+ Message::DeclareFunction(name, func, ty) => {
+ let mut scope_stack = self.scope_stack.borrow_mut();
+ if ty == FunctionVisibility::Local {
+ scope_stack.last_mut()
+ } else {
+ scope_stack.first_mut()
+ }
+ .expect("ICE: Scope stack is corrupted.")
+ .add_function(&name, func.clone());
+ }
+ Message::EnterFunctionScope(func) => {
+ *self.ident.borrow_mut() += 1;
+ self.enter_function_scope(func.clone());
+ }
+ Message::EnterModuleScope(name) => {
+ *self.ident.borrow_mut() += 1;
+ self.enter_module_scope(name.clone())
+ }
+ Message::ExitModuleScope(name) => {
+ *self.ident.borrow_mut() -= 1;
+ self.exit_module_scope(name.clone())
+ }
+ Message::RestoreModuleScope(name) => {
+ *self.ident.borrow_mut() += 1;
+ self.restore_module_scope(name.clone())
+ }
+ Message::EnterIfScope(_) => {
+ *self.ident.borrow_mut() += 1;
+ self.enter_anonymous_scope()
+ }
+ Message::EnterElseIfScope(_) => {
+ *self.ident.borrow_mut() += 1;
+ self.enter_anonymous_scope()
+ }
+ Message::EnterElseScope => {
+ *self.ident.borrow_mut() += 1;
+ self.enter_anonymous_scope()
+ }
+ Message::EnterAnonymousScope => {
+ *self.ident.borrow_mut() += 1;
+ self.enter_anonymous_scope()
+ }
+ Message::ExitScope => {
+ *self.ident.borrow_mut() -= 1;
+ self.exit_scope()
+ }
+ }
+ }
+
+ fn query(&self, query: Query) -> QueryResponse {
+ print!("{}", "│ ".repeat(*self.ident.borrow()));
+ println!("├── Query {:?}", query);
+ let response = match query {
+ Query::Function(func) => QueryResponse::Function(self.get_func(func)),
+ Query::FunctionGroup(name) => QueryResponse::FunctionGroup(self.get_func_group(&name)),
+ Query::Prefix => QueryResponse::Prefix(self.get_prefix()),
+ Query::Slot(name) => QueryResponse::Slot(self.get_slot(name)),
+ };
+ print!("{}", "│ ".repeat(*self.ident.borrow()));
+ println!("├── Response {:?}", response);
+ response
+ }
+
+ fn trace(&self, message: String) {
+ print!("{}", "│ ".repeat(*self.ident.borrow()));
+ println!("├── {}", message);
+ }
+
+ pub fn push(
+ &mut self,
+ name: &String,
+ module: CompilerUnit<'ctx>,
+ ) -> Option> {
+ self.modules.insert(name.clone(), module)
+ }
+
+ pub fn get_mut(&mut self, name: &String) -> Option<&mut Self> {
+ self.modules.get_mut(name)
+ }
+
+ pub fn decl(&'ctx self, root_builder: &Builder, ast: &AST) {
+ let dispatch = &|command: Message| self.dispatch(command);
+ let query = &|query: Query| self.query(query);
+ let trace = &|message: String| self.trace(message);
+ let basic_block = &|name: &str| self.basic_block(name);
+
+ decl::decl(
+ ast,
+ &mut CompilerContext::new(
+ self.path.clone(),
+ self.llvm_context,
+ self.llvm_module,
+ root_builder,
+ dispatch,
+ query,
+ trace,
+ basic_block,
+ ),
+ );
+ }
+
+ pub fn generics(&'ctx self, root_builder: &Builder, ast: &AST) {
+ let mut proc = self.generic_processor.borrow_mut();
+ let ast = proc
+ .extract_function_calls(ast)
+ .extract_tree(ast)
+ .generate_tree()
+ .generated_tree
+ .as_ref()
+ .unwrap();
+
+ self.decl(root_builder, ast);
+ self.codegen(root_builder, ast);
+ }
+
+ pub fn codegen(&'ctx self, root_builder: &Builder, ast: &AST) -> Option {
+ let dispatch = &|command: Message| self.dispatch(command);
+ let query = &|query: Query| self.query(query);
+ let trace = &|message: String| self.trace(message);
+ let basic_block = &|name: &str| self.basic_block(name);
+
+ cg::cg(
+ ast,
+ &CompilerContext::new(
+ self.path.clone(),
+ self.llvm_context,
+ self.llvm_module,
+ root_builder,
+ dispatch,
+ query,
+ trace,
+ basic_block,
+ ),
+ )
+ }
+
+ pub fn get_func_group(&self, name: &String) -> Option> {
+ for scope in self.scope_stack.borrow().iter().rev() {
+ if let Some(func) = scope.func_by_name(&name) {
+ return Some(func);
+ }
+ }
+
+ for scope in self.scope_stack.borrow().iter().rev() {
+ if let Some(func) = scope.get_template(&name) {
+ println!("Found template!");
+ }
+ }
+
+ None
+ }
+
+ pub fn get_func(&self, func: (String, &FunctionType)) -> Option> {
+ for scope in self.scope_stack.borrow().iter().rev() {
+ if let Some(group) = scope.func_by_name(&func.0) {
+ return find_func(group, func.1);
+ }
+ }
+
+ None
+ }
+
+ pub fn llvm_module_ref(&self) -> &Module {
+ &self.llvm_module
+ }
+
+ pub fn get_prefix(&self) -> Vec {
+ self.scope_stack
+ .borrow()
+ .iter()
+ .map(|s| s.name())
+ .filter(|n| n != &String::default())
+ .collect::>()
+ }
+
+ pub fn basic_block(&self, name: &str) -> LLVMBasicBlockRef {
+ for scope in self.scope_stack.borrow().iter().rev() {
+ let bb = scope.bb(self, &name);
+ if let Some(bb) = bb {
+ return bb;
+ }
+ }
+ panic!("Compiler broke. Scope stack is corrupted.");
+ }
+}
+
+#[macro_export]
+macro_rules! prefix {
+ (call $ctx: expr, $name: expr) => {{
+ if let crate::codegen::unit::compiler::QueryResponse::Prefix(mut prefix) =
+ $ctx.query(crate::codegen::unit::compiler::Query::Prefix)
+ {
+ prefix.pop();
+ prefix.push($name);
+ prefix
+ } else {
+ panic!("PREFIX ICE")
+ }
+ }};
+ (call module $ctx: expr, $name: expr) => {{
+ if let crate::codegen::unit::compiler::QueryResponse::Prefix(mut prefix) =
+ $ctx.query(crate::codegen::unit::compiler::Query::Prefix)
+ {
+ prefix.pop();
+ prefix.extend($name);
+ prefix
+ } else {
+ panic!("PREFIX ICE")
+ }
+ }};
+ ($ctx: expr, $name: expr) => {{
+ if let crate::codegen::unit::compiler::QueryResponse::Prefix(mut prefix) =
+ $ctx.query(crate::codegen::unit::compiler::Query::Prefix)
+ {
+ prefix.push($name);
+ prefix
+ } else {
+ panic!("PREFIX ICE")
+ }
+ }};
+ ($ctx: expr) => {{
+ if let crate::codegen::unit::compiler::QueryResponse::Prefix(prefix) =
+ $ctx.query(crate::codegen::unit::compiler::Query::Prefix)
+ {
+ prefix
+ } else {
+ panic!("PREFIX ICE")
+ }
+ }};
+}
diff --git a/comp-be/src/codegen/unit/decl/expr.rs b/comp-be/src/codegen/unit/decl/expr.rs
new file mode 100644
index 0000000..15370d0
--- /dev/null
+++ b/comp-be/src/codegen/unit/decl/expr.rs
@@ -0,0 +1,15 @@
+use parser::ast::Expression;
+
+use crate::codegen::unit::{declare_function, CompilerContext, Message};
+
+pub fn decl(expr: &Expression, ctx: &mut CompilerContext) {
+ match expr {
+ Expression::Function { type_names, .. } if type_names.len() == 0 => {
+ declare_function(ctx, expr)
+ }
+ Expression::Function { name, .. } => {
+ ctx.dispatch(Message::PushFunctionTemplate(name.clone(), expr.clone()));
+ }
+ _ => panic!("Top level {:?} unsupported", expr),
+ }
+}
diff --git a/comp-be/src/codegen/unit/decl/mod.rs b/comp-be/src/codegen/unit/decl/mod.rs
new file mode 100644
index 0000000..da48c01
--- /dev/null
+++ b/comp-be/src/codegen/unit/decl/mod.rs
@@ -0,0 +1,21 @@
+mod expr;
+
+use parser::ast::AST;
+
+use super::{CompilerContext, Message};
+
+pub fn decl(ast: &AST, ctx: &mut CompilerContext) {
+ match ast {
+ AST::Expr(expr) => expr::decl(expr, ctx),
+ AST::Module(name, ast) => {
+ ctx.dispatch(Message::EnterModuleScope(name.clone()));
+ super::decl(ast, ctx);
+ ctx.dispatch(Message::ExitModuleScope(name.clone()));
+ }
+ AST::File(nodes) => nodes
+ .iter()
+ .fold(Some(()), |_, ast| Some(decl(ast, ctx)))
+ .unwrap(),
+ _ => todo!("{:?}", ast),
+ }
+}
diff --git a/comp-be/src/codegen/unit/function.rs b/comp-be/src/codegen/unit/function.rs
index e0449a2..c473256 100644
--- a/comp-be/src/codegen/unit/function.rs
+++ b/comp-be/src/codegen/unit/function.rs
@@ -1,29 +1,45 @@
use crate::{
codegen::builder::cast,
codegen::{
- builder::core,
+ builder::base,
mangle_v1::NameMangler,
- unit::{Mutability, Slot},
- AatbeModule, CompileError, ValueTypePair,
+ unit::{
+ cg::expr, CompilerContext, FunctionVisibility, Message, Mutability, Query,
+ QueryResponse, Slot,
+ },
+ CompileError, ValueTypePair,
},
fmt::AatbeFmt,
+ prefix,
ty::LLVMTyInCtx,
};
use llvm_sys_wrapper::Function;
-use std::collections::HashMap;
-use std::ops::Deref;
+use std::{
+ cell::RefCell,
+ collections::HashMap,
+ ops::Deref,
+ rc::{Rc, Weak},
+};
+
+use guard::guard;
-use parser::ast::{Expression, FunctionType, PrimitiveType};
+use parser::ast::{Expression, FunctionType, Type};
use llvm_sys_wrapper::{Builder, LLVMBasicBlockRef};
-#[derive(Debug)]
+#[derive(Clone)]
pub struct Func {
ty: FunctionType,
- name: String,
+ ident: String,
inner: Function,
}
+impl std::fmt::Debug for Func {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", AatbeFmt::fmt(self))
+ }
+}
+
impl AatbeFmt for &Func {
fn fmt(self) -> String {
format!(
@@ -33,28 +49,28 @@ impl AatbeFmt for &Func {
} else {
String::default()
},
- self.name,
+ self.ident,
(&self.ty).fmt()
)
}
}
-pub type FuncTyMap = Vec;
-pub type FunctionMap = HashMap;
+pub type FuncTyMap = Vec>;
+pub type FunctionMap = HashMap>;
-pub fn find_func<'a>(map: &'a FuncTyMap, ty: &FunctionType) -> Option<&'a Func> {
- for func in map {
+pub fn find_func<'a>(map: RefCell, ty: &FunctionType) -> Option> {
+ for func in map.borrow().iter() {
if &func.ty == ty {
- return Some(func);
+ return Some(Rc::downgrade(func));
}
}
return None;
}
-pub fn find_function<'a>(map: &'a FuncTyMap, args: &Vec) -> Option<&'a Func> {
- for func in map {
+pub fn find_function<'a>(map: RefCell, args: &Vec) -> Option> {
+ for func in map.borrow().iter() {
if func.accepts(args) {
- return Some(func);
+ return Some(Rc::downgrade(func));
}
}
return None;
@@ -68,15 +84,15 @@ impl Deref for Func {
}
impl Func {
- pub fn new(ty: FunctionType, name: String, inner: Function) -> Self {
- Self { ty, name, inner }
+ pub fn new(ty: FunctionType, ident: String, inner: Function) -> Self {
+ Self { ty, ident, inner }
}
pub fn ty(&self) -> &FunctionType {
&self.ty
}
- pub fn ret_ty(&self) -> &PrimitiveType {
+ pub fn ret_ty(&self) -> &Type {
&self.ty.ret_ty
}
@@ -85,28 +101,28 @@ impl Func {
}
pub fn bb(&self, name: String) -> LLVMBasicBlockRef {
- self.inner.append_basic_block(name.as_ref())
+ self.inner.append_basic_block(&name)
}
- fn accepts(&self, args: &Vec) -> bool {
+ fn accepts(&self, args: &Vec) -> bool {
let params = &self.ty.params;
- if params.len() != args.len() && !(params.contains(&PrimitiveType::Varargs)) {
+ if params.len() != args.len() && !(params.contains(&Type::Varargs)) {
return false;
};
for (i, param) in params.iter().enumerate() {
- if matches!(param, PrimitiveType::Varargs) {
+ if matches!(param, Type::Varargs) {
continue;
}
let arg = &args[i];
match param {
- PrimitiveType::Varargs => continue,
- PrimitiveType::NamedType {
+ Type::Varargs => continue,
+ Type::NamedType {
ty: Some(box t), ..
} if t != arg => return false,
- PrimitiveType::NamedType {
+ Type::NamedType {
ty: Some(box t), ..
} if t == arg => return true,
t if t != arg => return false,
@@ -118,32 +134,41 @@ impl Func {
}
}
-pub fn declare_function(module: &mut AatbeModule, function: &Expression) {
+pub fn declare_function(ctx: &CompilerContext, function: &Expression) {
match function {
Expression::Function {
ty,
- export,
+ public,
type_names,
name,
..
} if type_names.len() == 0 => {
- let func = module
- .llvm_module_ref()
- .get_or_add_function(&function.mangle(module), ty.llvm_ty_in_ctx(module));
+ let func = ctx
+ .llvm_module
+ .get_or_add_function(&function.mangle(&ctx), ty.llvm_ty_in_ctx(&ctx));
+ let name = prefix!(ctx, name.clone()).join("::");
let func = Func::new(ty.clone(), name.clone(), func);
- if !export {
- module.add_function(&name, func);
+ if !public {
+ ctx.dispatch(Message::DeclareFunction(
+ name,
+ func,
+ FunctionVisibility::Local,
+ ));
} else {
- module.export_function(&name, func);
+ ctx.dispatch(Message::DeclareFunction(
+ name,
+ func,
+ FunctionVisibility::Public,
+ ));
}
}
_ => unimplemented!("{:?}", function),
}
}
-pub fn declare_and_compile_function(
- module: &mut AatbeModule,
+pub fn declare_and_compile_function<'ctx>(
+ ctx: &CompilerContext,
func: &Expression,
) -> Option {
match func {
@@ -154,53 +179,46 @@ pub fn declare_and_compile_function(
ext: true,
} => None,
_ => {
- let builder = Builder::new_in_context(module.llvm_context_ref().as_ref());
- module.start_scope_with_function((name.clone(), ty.clone()), builder);
- codegen_function(module, func);
- inject_function_in_scope(module, func);
- let ret_val = module.codegen_expr(
- &body
- .as_ref()
- .expect("ICE Function with no body but not external"),
- );
-
- // TODO: Typechecks
- if has_return_type(ty) {
- if let Some(val) = ret_val {
- match val.prim() {
- PrimitiveType::VariantType(variant) => {
- let parent_ty = module
- .typectx_ref()
- .get_parent_for_variant(variant)
- .expect("ICE: Variant without parent");
- let ret_ty = *ty.ret_ty.clone();
- core::ret(
- module,
- (cast::child_to_parent(module, val, parent_ty), ret_ty).into(),
- )
- }
- _ => core::ret(module, val),
- };
+ ctx.in_function_scope((name.clone(), ty.clone()), |ctx| {
+ inject_function_in_scope(&ctx, func);
+
+ codegen_function(&ctx, func);
+
+ let ret_val = expr::cg(
+ &body
+ .as_ref()
+ .expect("ICE Function with no body but not external"),
+ &ctx,
+ );
+
+ if !has_return_type(ty) {
+ base::ret_void(&ctx);
} else {
- module.add_error(CompileError::ExpectedReturn {
- function: func.clone().fmt(),
- ty: ty.fmt(),
- })
+ if let Some(val) = ret_val {
+ match val.prim() {
+ Type::VariantType(_variant) => todo!(),
+ _ => base::ret(&ctx, val),
+ };
+ } else {
+ // TODO: Error
+ /*
+ module.add_error(CompileError::ExpectedReturn {
+ function: func.clone().fmt(),
+ ty: ty.fmt(),
+ }) */
+ todo!()
+ }
}
- } else {
- core::ret_void(module);
- }
-
- module.exit_scope();
- None
+ None
+ })
}
},
_ => unreachable!(),
}
}
-pub fn codegen_function(module: &mut AatbeModule, function: &Expression) {
+pub fn codegen_function(ctx: &CompilerContext, function: &Expression) {
match function {
Expression::Function {
attributes,
@@ -208,24 +226,27 @@ pub fn codegen_function(module: &mut AatbeModule, function: &Expression) {
ty,
..
} => {
- let func = module.get_func((name.clone(), ty.clone())).unwrap();
+ let func = ctx.query(Query::Function((prefix!(ctx).join("::"), ty)));
+
+ guard!(let QueryResponse::Function(Some(func)) = func else { unreachable!(); });
+ let func = func.upgrade().expect("ICE");
if !attributes.is_empty() {
for attr in attributes {
match attr.to_lowercase().as_ref() {
- "entry" => core::pos_at_end(module, func.bb("entry".to_string())),
+ "entry" => base::pos_at_end(ctx, func.bb("entry".to_string())),
_ => panic!("Cannot decorate function with {}", name),
};
}
} else {
- core::pos_at_end(module, func.bb(String::default()));
+ base::pos_at_end(ctx, func.bb(String::default()));
}
}
_ => unreachable!(),
}
}
-pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression) {
+pub fn inject_function_in_scope(ctx: &CompilerContext, function: &Expression) {
match function {
Expression::Function {
name: fname, ty, ..
@@ -241,21 +262,17 @@ pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression)
for (pos, ty) in params
.into_iter()
.filter(|ty| match ty {
- PrimitiveType::Symbol(_) => false,
+ Type::Symbol(_) => false,
_ => true,
})
.enumerate()
{
match ty {
- PrimitiveType::NamedType {
+ Type::NamedType {
name,
- ty:
- Some(
- box PrimitiveType::TypeRef(_)
- | box PrimitiveType::Array { .. },
- ),
+ ty: Some(box Type::TypeRef(_) | box Type::Array { .. }),
} => {
- let arg = module
+ /*let arg = module
.get_func((fname.clone(), fty.clone()))
.expect("Compiler borked. Functions borked")
.get_param(pos as u32);
@@ -265,9 +282,9 @@ pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression)
name,
Slot::Variable {
mutable: match ty {
- PrimitiveType::Array { .. }
- | PrimitiveType::NamedType {
- ty: Some(box PrimitiveType::Array { .. }),
+ Type::Array { .. }
+ | Type::NamedType {
+ ty: Some(box Type::Array { .. }),
..
} => Mutability::Mutable,
_ => Mutability::Immutable,
@@ -276,24 +293,24 @@ pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression)
ty: ty.clone(),
value: ptr,
},
- );
+ );*/
+ todo!()
}
- PrimitiveType::NamedType {
+ Type::NamedType {
name,
- ty: Some(box PrimitiveType::Ref(ty) | ty),
+ ty: Some(box Type::Ref(ty) | ty),
} => {
- module.push_in_scope(
- name,
- Slot::FunctionArgument(
- module
- .get_func((fname.clone(), fty.clone()))
- .expect("Compiler borked. Functions borked")
- .get_param(pos as u32),
- *ty.clone(),
- ),
- );
+ guard!(let QueryResponse::Function(Some(func)) =
+ ctx.query(Query::Function((prefix!(ctx).join("::"), fty)))
+ else { unreachable!() });
+
+ let func = func.upgrade().expect("ICE");
+ ctx.dispatch(Message::PushInScope(
+ name.clone(),
+ Slot::FunctionArgument(func.get_param(pos as u32), *ty.clone()),
+ ))
}
- PrimitiveType::Unit | PrimitiveType::Symbol(_) => {}
+ Type::Unit | Type::Symbol(_) => {}
_ => unimplemented!("{:?}", ty),
}
}
@@ -307,7 +324,7 @@ pub fn inject_function_in_scope(module: &mut AatbeModule, function: &Expression)
fn has_return_type(func: &FunctionType) -> bool {
match func.ret_ty {
- box PrimitiveType::Unit => false,
+ box Type::Unit => false,
_ => true,
}
}
diff --git a/comp-be/src/codegen/unit/generic/gen.rs b/comp-be/src/codegen/unit/generic/gen.rs
new file mode 100644
index 0000000..3368a9a
--- /dev/null
+++ b/comp-be/src/codegen/unit/generic/gen.rs
@@ -0,0 +1,103 @@
+use std::collections::HashMap;
+
+use parser::ast::{Expression, FunctionType, IdentPath, Type, AST};
+
+use super::Processor;
+
+use guard::guard;
+
+pub fn gen(ast: &AST, proc: &Processor) -> Option {
+ match ast {
+ AST::Module(..) => {
+ // TODO: Module
+ None
+ }
+ AST::File(body) => Some(AST::File(
+ body.iter()
+ .filter_map(|ast| gen_tree(ast, proc))
+ .flatten()
+ .collect::>(),
+ )),
+ _ => todo!("{:?}", ast),
+ }
+}
+
+fn gen_tree(ast: &AST, proc: &Processor) -> Option> {
+ match ast {
+ AST::Module(..) => {
+ // TODO: Module
+ None
+ }
+ AST::Expr(expr) => gen_expr(expr, proc).and_then(|exprs| {
+ Some(
+ exprs
+ .iter()
+ .map(|expr| AST::Expr(expr.clone()))
+ .collect::>(),
+ )
+ }),
+ _ => todo!("{:?}", ast),
+ }
+}
+
+fn gen_expr(expr: &Expression, proc: &Processor) -> Option> {
+ match expr {
+ Expression::Function {
+ type_names,
+ name,
+ ty:
+ FunctionType {
+ ext,
+ ret_ty,
+ params,
+ },
+ body,
+ attributes,
+ public,
+ } => {
+ guard!(let Some(types) = proc
+ .function_calls
+ .get(&IdentPath::Local(name.clone())) else { return None; });
+
+ Some(
+ types
+ .iter()
+ .map(|set| {
+ let map = type_names.iter().zip(set).collect::>();
+
+ Expression::Function {
+ type_names: vec![],
+ name: name.clone(),
+ ty: FunctionType {
+ ext: *ext,
+ ret_ty: box resolve_type(ret_ty, &map),
+ params: params
+ .iter()
+ .map(|ty| resolve_type(ty, &map))
+ .collect::>(),
+ },
+ body: body.clone(),
+ attributes: attributes.clone(),
+ public: *public,
+ }
+ })
+ .collect(),
+ )
+ }
+ _ => todo!("{:?}", expr),
+ }
+}
+
+fn resolve_type(ty: &Type, map: &HashMap<&String, &Type>) -> Type {
+ match ty {
+ Type::NamedType {
+ name,
+ ty: Some(box ty),
+ } => Type::NamedType {
+ name: name.clone(),
+ ty: Some(box resolve_type(ty, map)),
+ },
+ Type::TypeRef(name) => map.get(name).cloned().unwrap().clone(),
+ _ => ty.clone(),
+ }
+}
diff --git a/comp-be/src/codegen/unit/generic/mod.rs b/comp-be/src/codegen/unit/generic/mod.rs
new file mode 100644
index 0000000..c1195ba
--- /dev/null
+++ b/comp-be/src/codegen/unit/generic/mod.rs
@@ -0,0 +1,94 @@
+use std::collections::{HashMap, HashSet};
+
+use parser::ast::{Expression, IdentPath, Type, AST};
+
+mod gen;
+
+#[derive(Debug)]
+pub struct Processor {
+ pub(super) function_calls: HashMap>>,
+ extracted_tree: Option,
+ pub generated_tree: Option,
+}
+
+impl Processor {
+ pub fn new() -> Self {
+ Self {
+ function_calls: HashMap::new(),
+ extracted_tree: None,
+ generated_tree: None,
+ }
+ }
+
+ pub fn extract_function_calls(&mut self, ast: &AST) -> &mut Self {
+ match ast {
+ AST::Module(..) => {
+ // TODO: Module
+ }
+ AST::File(body) => body.iter().for_each(|ast| {
+ self.extract_function_calls(ast);
+ }),
+ AST::Expr(expr) => self.from_expression(expr),
+ _ => todo!("{:?}", ast),
+ };
+
+ self
+ }
+
+ fn from_expression(&mut self, expr: &Expression) {
+ match expr {
+ Expression::Function {
+ body: Some(box body),
+ ..
+ } => self.from_expression(body),
+ Expression::Call { name, types, .. } if types.len() > 0 => {
+ self.insert_function_call(name, types.clone())
+ }
+ Expression::Block(body) => body.iter().for_each(|e| self.from_expression(e)),
+ _ => {}
+ }
+ }
+
+ pub fn extract_tree(&mut self, ast: &AST) -> &mut Self {
+ println!("{:#?}", ast);
+ self.extracted_tree = extract_ast(ast);
+ println!("{:#?}", self.extracted_tree);
+ self
+ }
+
+ pub fn generate_tree(&mut self) -> &mut Self {
+ let ast = self.extracted_tree.as_ref().unwrap();
+ self.generated_tree = gen::gen(ast, &self);
+ println!("{:#?}", self.generated_tree);
+ self
+ }
+
+ fn insert_function_call(&mut self, name: &IdentPath, types: Vec) {
+ if !self.function_calls.contains_key(name) {
+ self.function_calls.insert(name.clone(), HashSet::new());
+ }
+
+ self.function_calls.get_mut(name).unwrap().insert(types);
+ }
+}
+
+fn extract_ast(ast: &AST) -> Option {
+ match ast {
+ AST::Module(..) => {
+ // TODO: Module
+ None
+ }
+ AST::File(body) => Some(AST::File(
+ body.iter().filter_map(extract_ast).collect::>(),
+ )),
+ AST::Expr(expr) => extract_expr(expr).and_then(|expr| Some(AST::Expr(expr))),
+ _ => todo!("{:?}", ast),
+ }
+}
+
+fn extract_expr(expr: &Expression) -> Option {
+ match expr {
+ Expression::Function { type_names, .. } if type_names.len() > 0 => Some(expr.clone()),
+ _ => None,
+ }
+}
diff --git a/comp-be/src/codegen/unit/mod.rs b/comp-be/src/codegen/unit/mod.rs
index fea2d57..f41e7cc 100644
--- a/comp-be/src/codegen/unit/mod.rs
+++ b/comp-be/src/codegen/unit/mod.rs
@@ -1,7 +1,7 @@
use llvm_sys_wrapper::{Builder, LLVMValueRef};
use crate::codegen::{AatbeModule, ValueTypePair};
-use parser::ast::{BindType, PrimitiveType};
+use parser::ast::{BindType, Type};
pub mod function;
pub use function::{
@@ -11,6 +11,19 @@ pub use function::{
pub mod variable;
pub use variable::{alloc_variable, init_record, store_value};
+pub mod compiler;
+pub use compiler::{
+ CompilerContext, CompilerUnit, FunctionVisibility, Message, Query, QueryResponse,
+};
+
+pub mod decl;
+pub use decl::decl;
+
+pub mod cg;
+pub use cg::cg;
+
+pub mod generic;
+
#[derive(Debug, Clone)]
pub enum Mutability {
Immutable,
@@ -31,11 +44,11 @@ impl From<&BindType> for Mutability {
#[derive(Debug, Clone)]
pub enum Slot {
- FunctionArgument(LLVMValueRef, PrimitiveType),
+ FunctionArgument(LLVMValueRef, Type),
Variable {
mutable: Mutability,
name: String,
- ty: PrimitiveType,
+ ty: Type,
value: LLVMValueRef,
},
}
@@ -54,6 +67,20 @@ impl Into for &Slot {
}
}
+impl Into for Slot {
+ fn into(self) -> ValueTypePair {
+ match self {
+ Slot::FunctionArgument(arg, ty) => (arg, ty).into(),
+ Slot::Variable {
+ mutable: _,
+ name: _,
+ ty,
+ value,
+ } => (value, ty).into(),
+ }
+ }
+}
+
impl Into for &Slot {
fn into(self) -> LLVMValueRef {
match self {
@@ -77,24 +104,24 @@ impl Slot {
match self {
Slot::Variable {
ty:
- PrimitiveType::TypeRef(rec)
- | PrimitiveType::NamedType {
+ Type::TypeRef(rec)
+ | Type::NamedType {
name: _,
- ty: Some(box PrimitiveType::TypeRef(rec)),
+ ty: Some(box Type::TypeRef(rec)),
},
..
} => Some(rec.clone()),
Slot::FunctionArgument(
_arg,
- PrimitiveType::TypeRef(rec)
- | PrimitiveType::Pointer(box PrimitiveType::TypeRef(rec)),
+ Type::TypeRef(rec)
+ | Type::Pointer(box Type::TypeRef(rec)),
) => Some(rec.clone()),
Slot::Variable {
ty:
- PrimitiveType::VariantType(name)
- | PrimitiveType::NamedType {
+ Type::VariantType(name)
+ | Type::NamedType {
name: _,
- ty: Some(box PrimitiveType::VariantType(name)),
+ ty: Some(box Type::VariantType(name)),
},
..
} => Some(name.clone()),
@@ -102,13 +129,13 @@ impl Slot {
}
}
- pub fn get_index(&self, module: &AatbeModule, name: &String) -> Option<(u32, PrimitiveType)> {
+ pub fn get_index(&self, module: &AatbeModule, name: &String) -> Option<(u32, Type)> {
match self {
Slot::Variable {
ty:
- PrimitiveType::NamedType {
+ Type::NamedType {
name: _,
- ty: Some(box PrimitiveType::TypeRef(record)),
+ ty: Some(box Type::TypeRef(record)),
},
..
} => match module.typectx_ref().get_record(record) {
@@ -122,25 +149,25 @@ impl Slot {
pub fn load_var(&self, builder: &Builder) -> LLVMValueRef {
match self {
Slot::Variable {
- ty: PrimitiveType::Array { .. },
+ ty: Type::Array { .. },
..
}
| Slot::Variable {
ty:
- PrimitiveType::NamedType {
- ty: Some(box PrimitiveType::Array { .. }),
+ Type::NamedType {
+ ty: Some(box Type::Array { .. }),
..
},
..
} => self.into(),
Slot::Variable {
- ty: PrimitiveType::Slice { .. },
+ ty: Type::Slice { .. },
..
}
| Slot::Variable {
ty:
- PrimitiveType::NamedType {
- ty: Some(box PrimitiveType::Slice { .. }),
+ Type::NamedType {
+ ty: Some(box Type::Slice { .. }),
..
},
..
@@ -152,17 +179,17 @@ impl Slot {
Mutability::Constant => self.into(),
_ => builder.build_load(self.into()),
},
- Slot::FunctionArgument(_, PrimitiveType::Slice { .. }) => {
+ Slot::FunctionArgument(_, Type::Slice { .. }) => {
builder.build_load(self.into())
}
Slot::FunctionArgument(_, _) => self.into(),
}
}
- pub fn var_ty(&self) -> &PrimitiveType {
+ pub fn var_ty(&self) -> &Type {
match self {
Slot::Variable { ty, .. } => match ty {
- PrimitiveType::NamedType {
+ Type::NamedType {
name: _,
ty: Some(ty),
} => ty,
@@ -175,8 +202,8 @@ impl Slot {
pub fn get_mutability(&self) -> &Mutability {
match self {
Slot::Variable { mutable, .. } => mutable,
- Slot::FunctionArgument(_, PrimitiveType::Array { .. }) => &Mutability::Mutable,
- Slot::FunctionArgument(_, PrimitiveType::Slice { .. }) => &Mutability::Mutable,
+ Slot::FunctionArgument(_, Type::Array { .. }) => &Mutability::Mutable,
+ Slot::FunctionArgument(_, Type::Slice { .. }) => &Mutability::Mutable,
_ => panic!("ICE get_mutability: Not a variable {:?}", self),
}
}
diff --git a/comp-be/src/codegen/unit/variable.rs b/comp-be/src/codegen/unit/variable.rs
index d5f3add..00c5702 100644
--- a/comp-be/src/codegen/unit/variable.rs
+++ b/comp-be/src/codegen/unit/variable.rs
@@ -1,14 +1,16 @@
use crate::ty::infer::infer_type;
use crate::{
codegen::{
- unit::{Mutability, Slot},
+ builder::{base, value},
+ unit::{cg::expr, CompilerContext, Message, Mutability, Query, QueryResponse, Slot},
AatbeModule, CompileError, ValueTypePair,
},
fmt::AatbeFmt,
ty::{record::store_named_field, LLVMTyInCtx, TypeKind},
};
-use parser::ast::{AtomKind, Expression, LValue, PrimitiveType};
+use guard::guard;
+use parser::ast::{AtomKind, Expression, LValue, Type};
macro_rules! rec_name {
($name:expr, $types:expr) => {{
@@ -31,25 +33,26 @@ macro_rules! rec_name {
}};
}
-pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option {
+pub fn alloc_variable(variable: &Expression, ctx: &CompilerContext) -> Option {
match variable {
Expression::Decl {
- ty: PrimitiveType::NamedType { name, ty },
+ ty: Type::NamedType { name, ty },
value,
exterior_bind,
} => {
- /*let mut vtp = None;
+ let mut vtp = None;
let ty = match ty {
Some(ty) => match ty {
- box PrimitiveType::GenericTypeRef(name, types) => {
- let rec = rec_name!(name.clone(), types);
+ box Type::GenericTypeRef(name, types) => {
+ /*let rec = rec_name!(name.clone(), types);
if !module.typectx_ref().get_record(&rec).is_ok() {
module.propagate_types_in_record(name, types.clone());
}
- PrimitiveType::TypeRef(rec.clone())
+ Type::TypeRef(rec.clone())*/
+ todo!()
}
- box PrimitiveType::VariantType(_) => {
- if let Some(e) = value {
+ box Type::VariantType(_) => {
+ /*if let Some(e) = value {
let pair = module.codegen_expr(e)?;
let ty = pair.prim().clone();
@@ -57,7 +60,8 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option
ty
} else {
unreachable!();
- }
+ }*/
+ todo!()
}
_ => *ty.clone(),
},
@@ -69,18 +73,19 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option
values: _,
} = e
{
- let rec = rec_name!(record.clone(), types);
+ /*let rec = rec_name!(record.clone(), types);
if types.len() == 0 {
- PrimitiveType::TypeRef(rec.clone())
+ Type::TypeRef(rec.clone())
} else {
if !module.typectx_ref().get_record(&rec).is_ok() {
module.propagate_types_in_record(record, types.clone());
}
- PrimitiveType::TypeRef(rec.clone())
- }
+ Type::TypeRef(rec.clone())
+ }*/
+ todo!()
} else {
- let pair = module.codegen_expr(e)?;
+ let pair = expr::cg(e, ctx)?;
let ty = pair.prim().clone();
vtp = Some(pair);
@@ -90,10 +95,10 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option
unreachable!();
}
}
- };*/
+ };
- /*if let PrimitiveType::Newtype(..) | PrimitiveType::VariantType(..) = ty {
- module.push_in_scope(
+ if let Type::Newtype(..) | Type::VariantType(..) = ty {
+ /*module.push_in_scope(
name,
Slot::Variable {
mutable: Mutability::from(exterior_bind),
@@ -102,52 +107,45 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option
value: *vtp.unwrap(),
},
);
- return Some(ty.clone());
- }*/
+ return Some(ty.clone());*/
+ todo!()
+ }
if value.is_none() {
- let ty = ty.as_ref().expect("ICE: Ty none for none value");
- let val_ref = module
- .llvm_builder_ref()
- .build_alloca_with_name(ty.llvm_ty_in_ctx(module), name.as_ref());
+ let val_ref = base::alloca_with_name(ctx, ty.llvm_ty_in_ctx(ctx), &name);
- module.push_in_scope(
- name,
+ ctx.dispatch(Message::PushInScope(
+ name.clone(),
Slot::Variable {
mutable: Mutability::from(exterior_bind),
name: name.clone(),
- ty: *ty.clone(),
+ ty: ty.clone(),
value: val_ref,
},
- );
+ ));
- return Some(*ty.clone());
+ return Some(ty);
}
// TODO: Variants, generic records
- let ty = infer_type(
- module,
- &*(value.as_ref().expect("ICE: Value cannot be none")),
- );
+ let ty = infer_type(ctx, &*(value.as_ref().expect("ICE: Value cannot be none")));
if ty.is_none() {
panic!("ICE: ty is none {:?} value", value);
}
let (ty, constant) = ty.unwrap();
- let var_ref = module
- .llvm_builder_ref()
- .build_alloca_with_name(ty.llvm_ty_in_ctx(module), name.as_ref());
+ let var_ref = base::alloca_with_name(ctx, ty.llvm_ty_in_ctx(ctx), &name);
- module.push_in_scope(
- name,
+ ctx.dispatch(Message::PushInScope(
+ name.clone(),
Slot::Variable {
mutable: Mutability::from(exterior_bind),
name: name.clone(),
ty: ty.clone(),
value: var_ref,
},
- );
+ ));
if let Some(e) = value {
if let box Expression::RecordInit {
@@ -156,7 +154,7 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option
values,
} = e
{
- if ty.inner() != &PrimitiveType::TypeRef(rec_name!(record.clone(), types)) {
+ /*if ty.inner() != &Type::TypeRef(rec_name!(record.clone(), types)) {
module.add_error(CompileError::ExpectedType {
expected_ty: ty.inner().fmt(),
found_ty: record.clone(),
@@ -171,11 +169,12 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option
types: types.clone(),
values: values.to_vec(),
},
- );
+ );*/
+ todo!()
} else {
match ty.clone() {
- PrimitiveType::Array { ref ty, len } if !constant => {
- if let box Expression::Atom(AtomKind::Array(exprs)) = e {
+ Type::Array { ref ty, len } if !constant => {
+ /*if let box Expression::Atom(AtomKind::Array(exprs)) = e {
let vals = exprs
.iter()
.filter_map(|e| module.codegen_expr(e))
@@ -207,20 +206,22 @@ pub fn alloc_variable(module: &mut AatbeModule, variable: &Expression) -> Option
});
} else {
panic!("ICE: arr ty not arr val");
- }
+ }*/
+ todo!()
}
_ => {
- let val = module.codegen_expr(e)?;
+ let val = expr::cg(e, ctx)?;
if val.prim() != ty.inner() {
- module.add_error(CompileError::ExpectedType {
+ /*module.add_error(CompileError::ExpectedType {
expected_ty: ty.inner().fmt(),
found_ty: val.prim().fmt(),
value: value.as_ref().unwrap().fmt(),
- });
+ });*/
+ todo!("Error")
};
- module.llvm_builder_ref().build_store(*val, var_ref);
+ base::store(ctx, *val, var_ref);
}
};
}
@@ -236,7 +237,8 @@ pub fn init_record(
lval: &LValue,
rec: &Expression,
) -> Option {
- fn get_lval(module: &mut AatbeModule, lvalue: &LValue) -> Option {
+ todo!()
+ /*fn get_lval(module: &mut AatbeModule, lvalue: &LValue) -> Option {
match lvalue {
LValue::Ident(name) => match module.get_var(name) {
None => panic!("Cannot find variable {}", name),
@@ -250,7 +252,7 @@ pub fn init_record(
if let Some(val) = val {
match val.ty() {
- TypeKind::Primitive(PrimitiveType::Str) => {
+ TypeKind::Primitive(Type::Str) => {
let gep = module
.llvm_builder_ref()
.build_inbounds_gep(*val, &mut [*index]);
@@ -258,7 +260,7 @@ pub fn init_record(
Some(
(
module.llvm_builder_ref().build_load(gep),
- PrimitiveType::Char,
+ Type::Char,
)
.into(),
)
@@ -325,64 +327,69 @@ pub fn init_record(
}
}),
_ => unreachable!(),
- }
+ }*/
}
pub fn store_value(
- module: &mut AatbeModule,
+ ctx: &CompilerContext,
lval: &LValue,
value: &Expression,
) -> Option {
- fn get_lval(module: &mut AatbeModule, lvalue: &LValue) -> Option {
+ fn get_lval(ctx: &CompilerContext, lvalue: &LValue) -> Option {
match lvalue {
- LValue::Ident(name) => match module.get_var(name) {
- None => panic!("Cannot find variable {}", name),
- Some(var) => {
- match var.get_mutability() {
- Mutability::Mutable | Mutability::Global => {}
- _ => panic!("Cannot reassign to immutable/constant {}", name),
- };
- Some(var.into())
- }
- },
- LValue::Accessor(parts) => Some(module.get_interior_pointer(parts.clone())?),
+ LValue::Ident(name) => {
+ guard!(let QueryResponse::Slot(Some(slot)) = ctx.query(Query::Slot(name)) else { panic!("Cannot find variable {}", name) });
+ match slot.get_mutability() {
+ Mutability::Mutable | Mutability::Global => {}
+ _ => panic!("Cannot reassign to immutable/constant {}", name),
+ };
+ Some(slot.into())
+ }
+ LValue::Accessor(parts) => todo!(), //Some(module.get_interior_pointer(parts.clone())?),
LValue::Deref(_) => unimplemented!("{:?}", lvalue),
LValue::Index(lval, index) => {
- let val = get_lval(module, lval);
- let index = module.codegen_expr(index).expect("ICE store_value index");
+ let val = get_lval(ctx, lval);
+ let index = expr::cg(index, ctx)?;
if let Some(val) = val {
match val.ty() {
- TypeKind::Primitive(PrimitiveType::Str) => {
- let load = module.llvm_builder_ref().build_load(*val);
- let gep = module
- .llvm_builder_ref()
- .build_inbounds_gep(load, &mut [*index]);
-
- Some((gep, PrimitiveType::Char).into())
- }
- TypeKind::Primitive(PrimitiveType::Array { ty: box ty, .. }) => {
- let gep = module.llvm_builder_ref().build_inbounds_gep(
- *val,
- &mut [module.llvm_context_ref().SInt32(0), *index],
- );
-
- Some((gep, ty).into())
- }
- TypeKind::Primitive(PrimitiveType::Slice { ty: box ty }) => {
- let arr = module.llvm_builder_ref().build_struct_gep(*val, 0);
- let gep = module.llvm_builder_ref().build_inbounds_gep(
- module.llvm_builder_ref().build_load(arr),
- &mut [module.llvm_context_ref().SInt32(0), *index],
- );
-
- Some((gep, ty).into())
- }
+ TypeKind::Primitive(Type::Str) => Some(
+ (
+ base::inbounds_gep(ctx, base::load(ctx, *val), &mut vec![*index]),
+ Type::Char,
+ )
+ .into(),
+ ),
+ TypeKind::Primitive(Type::Array { ty: box ty, .. }) => Some(
+ (
+ base::inbounds_gep(
+ ctx,
+ *val,
+ &mut vec![*value::s32(ctx, 0), *index],
+ ),
+ ty,
+ )
+ .into(),
+ ),
+ TypeKind::Primitive(Type::Slice { ty: box ty }) => Some(
+ (
+ base::inbounds_gep(
+ ctx,
+ base::load(ctx, base::struct_gep(ctx, *val, 0)),
+ &mut vec![*value::s32(ctx, 0), *index],
+ ),
+ ty,
+ )
+ .into(),
+ ),
_ => {
+ // TODO: Error
+ /*
module.add_error(CompileError::NotIndexable {
ty: val.prim().fmt(),
lval: lvalue.fmt(),
- });
+ });*/
+ todo!();
None
}
}
@@ -393,19 +400,21 @@ pub fn store_value(
}
}
- get_lval(module, lval).and_then(|var| {
- let val = module.codegen_expr(value)?;
+ get_lval(ctx, lval).and_then(|var| {
+ let val = expr::cg(value, ctx)?;
if var.prim() != val.prim().inner() {
- module.add_error(CompileError::AssignMismatch {
+ // TODO: Error
+ todo!("ERROR");
+ /*module.add_error(CompileError::AssignMismatch {
expected_ty: var.prim().fmt(),
found_ty: val.prim().fmt(),
value: value.fmt(),
var: lval.fmt(),
- });
+ });*/
None
} else {
- Some((module.llvm_builder_ref().build_store(*val, *var), var.ty()).into())
+ Some((base::store(ctx, *val, *var), var.ty()).into())
}
})
}
diff --git a/comp-be/src/fmt.rs b/comp-be/src/fmt.rs
index ebd3873..279bf5c 100644
--- a/comp-be/src/fmt.rs
+++ b/comp-be/src/fmt.rs
@@ -1,12 +1,23 @@
use parser::ast::{
- AtomKind, Boolean, Expression, FloatSize, FunctionType, IntSize, LValue, PrimitiveType,
+ AtomKind, Boolean, Expression, FloatSize, FunctionType, IdentPath, IntSize, LValue,
+ Type,
};
pub trait AatbeFmt {
fn fmt(self) -> String;
}
-impl AatbeFmt for PrimitiveType {
+impl AatbeFmt for &IdentPath {
+ fn fmt(self) -> String {
+ match self {
+ IdentPath::Local(path) => path.clone(),
+ IdentPath::Module(path) => path.join("::"),
+ IdentPath::Root(path) => format!("::{}", path.join("::")),
+ }
+ }
+}
+
+impl AatbeFmt for Type {
fn fmt(self) -> String {
(&self).fmt()
}
@@ -20,7 +31,7 @@ impl AatbeFmt for FunctionType {
impl AatbeFmt for &FunctionType {
fn fmt(self) -> String {
- let params = if self.params.len() == 1 && self.params[0] == PrimitiveType::Unit {
+ let params = if self.params.len() == 1 && self.params[0] == Type::Unit {
String::from("()")
} else {
format!(
@@ -39,43 +50,43 @@ impl AatbeFmt for &FunctionType {
}
}
-impl AatbeFmt for &PrimitiveType {
+impl AatbeFmt for &Type {
fn fmt(self) -> String {
match self {
- PrimitiveType::Str => String::from("str"),
- PrimitiveType::Bool => String::from("bool"),
- PrimitiveType::Int(bits) => match bits {
+ Type::Str => String::from("str"),
+ Type::Bool => String::from("bool"),
+ Type::Int(bits) => match bits {
IntSize::Bits8 => String::from("i8"),
IntSize::Bits16 => String::from("i16"),
IntSize::Bits32 => String::from("i32"),
IntSize::Bits64 => String::from("i64"),
},
- PrimitiveType::UInt(bits) => match bits {
+ Type::UInt(bits) => match bits {
IntSize::Bits8 => String::from("u8"),
IntSize::Bits16 => String::from("u16"),
IntSize::Bits32 => String::from("u32"),
IntSize::Bits64 => String::from("u64"),
},
- PrimitiveType::Float(bits) => match bits {
+ Type::Float(bits) => match bits {
FloatSize::Bits32 => String::from("f32"),
FloatSize::Bits64 => String::from("f64"),
},
- PrimitiveType::Varargs => String::from("..."),
- PrimitiveType::NamedType {
+ Type::Varargs => String::from("..."),
+ Type::NamedType {
name: _,
ty: Some(ty),
} => ty.clone().fmt(),
- PrimitiveType::Pointer(ty) => format!("{}*", ty.clone().fmt()),
- PrimitiveType::Char => String::from("char"),
- PrimitiveType::TypeRef(ty) => ty.clone(),
- PrimitiveType::Array { ty, len } => {
+ Type::Pointer(ty) => format!("{}*", ty.clone().fmt()),
+ Type::Char => String::from("char"),
+ Type::TypeRef(ty) => ty.clone(),
+ Type::Array { ty, len } => {
format!("{}[{}]", ty.clone().fmt(), len.to_string())
}
- PrimitiveType::Unit => String::from("()"),
- PrimitiveType::Ref(ty) => format!("&{}", ty.clone().fmt()),
- PrimitiveType::Function(func) => func.fmt(),
- PrimitiveType::Slice { ty } => format!("{}[]", ty.clone().fmt()),
- PrimitiveType::GenericTypeRef(name, types) => format!(
+ Type::Unit => String::from("()"),
+ Type::Ref(ty) => format!("&{}", ty.clone().fmt()),
+ Type::Function(func) => func.fmt(),
+ Type::Slice { ty } => format!("{}[]", ty.clone().fmt()),
+ Type::GenericTypeRef(name, types) => format!(
"{}[{}]",
name,
types
@@ -84,8 +95,8 @@ impl AatbeFmt for &PrimitiveType {
.collect::>()
.join(", ")
),
- PrimitiveType::Newtype(name) => name.clone(),
- PrimitiveType::VariantType(name) => name.clone(),
+ Type::Newtype(name) => name.clone(),
+ Type::VariantType(name) => name.clone(),
_ => panic!("ICE fmt {:?}", self),
}
}
@@ -94,8 +105,8 @@ impl AatbeFmt for &PrimitiveType {
impl AatbeFmt for &AtomKind {
fn fmt(self) -> String {
match self {
- AtomKind::StringLiteral(lit) => format!("\"{}\"", lit),
- AtomKind::CharLiteral(lit) => format!("{}", lit),
+ AtomKind::StringLiteral(lit) => format!("{:?}", lit),
+ AtomKind::CharLiteral(lit) => format!("{:?}", lit),
AtomKind::Integer(val, ty) => format!("{}{}", val, ty.fmt()),
AtomKind::Floating(val, ty) => format!("{}{}", val, ty.fmt()),
AtomKind::Bool(Boolean::True) => String::from("true"),
@@ -155,7 +166,7 @@ impl AatbeFmt for &Expression {
),
Expression::Call { name, types, args } => format!(
"{}{} {}",
- name,
+ name.fmt(),
if types.len() > 0 {
format!(
"[{}]",
@@ -175,16 +186,20 @@ impl AatbeFmt for &Expression {
),
Expression::Function {
name,
- export,
+ public,
ty: ty @ FunctionType { ext, .. },
..
} => format!(
"{}{}fn {}{}",
- if *export { "exp " } else { "" },
+ if *public { "public " } else { "" },
if *ext { "ext " } else { "" },
name,
ty.fmt(),
),
+ Expression::Assign {
+ lval,
+ value: box value,
+ } => format!("{} = {}", lval.fmt(), value.fmt()),
_ => panic!("ICE fmt {:?}", self),
}
}
diff --git a/comp-be/src/lib.rs b/comp-be/src/lib.rs
index 8ffc12a..7972c04 100644
--- a/comp-be/src/lib.rs
+++ b/comp-be/src/lib.rs
@@ -2,11 +2,11 @@
box_syntax,
box_patterns,
type_ascription,
- vec_remove_item,
option_expect_none,
or_patterns,
bindings_after_at,
- type_alias_impl_trait
+ type_alias_impl_trait,
+ in_band_lifetimes,
)]
pub mod codegen;
diff --git a/comp-be/src/ty/aggregate.rs b/comp-be/src/ty/aggregate.rs
index 5d20d0e..b027520 100644
--- a/comp-be/src/ty/aggregate.rs
+++ b/comp-be/src/ty/aggregate.rs
@@ -1,5 +1,5 @@
use crate::{
- codegen::{AatbeModule, ValueTypePair},
+ codegen::{unit::CompilerContext, ValueTypePair},
ty::TypeResult,
};
@@ -8,28 +8,28 @@ use llvm_sys_wrapper::LLVMValueRef;
pub trait Aggregate {
fn gep_indexed_field(
&self,
- module: &AatbeModule,
+ ctx: &CompilerContext,
index: u32,
aggregate_ref: LLVMValueRef,
) -> TypeResult;
fn gep_named_field(
&self,
- module: &AatbeModule,
+ ctx: &CompilerContext,
name: &String,
aggregate_ref: LLVMValueRef,
) -> TypeResult;
fn gep_field(
&self,
- module: &AatbeModule,
+ ctx: &CompilerContext,
name: &String,
aggregate_ref: LLVMValueRef,
) -> TypeResult {
if let Ok(index) = name.parse::() {
- self.gep_indexed_field(module, index, aggregate_ref)
+ self.gep_indexed_field(ctx, index, aggregate_ref)
} else {
- self.gep_named_field(module, name, aggregate_ref)
+ self.gep_named_field(ctx, name, aggregate_ref)
}
}
}
diff --git a/comp-be/src/ty/infer.rs b/comp-be/src/ty/infer.rs
index 83eff39..bf0e95c 100644
--- a/comp-be/src/ty/infer.rs
+++ b/comp-be/src/ty/infer.rs
@@ -1,10 +1,15 @@
-use parser::ast::{AtomKind, Expression, PrimitiveType};
+use parser::ast::{AtomKind, Expression, IdentPath, Type};
-use crate::codegen::{unit::function::find_function, AatbeModule};
+use guard::guard;
-pub fn infer_type(module: &AatbeModule, expr: &Expression) -> Option<(PrimitiveType, bool)> {
+use crate::{
+ codegen::unit::{function::find_function, CompilerContext, Query, QueryResponse},
+ prefix,
+};
+
+pub fn infer_type(ctx: &CompilerContext, expr: &Expression) -> Option<(Type, bool)> {
match expr {
- Expression::Atom(atom) => infer_atom(module, &atom),
+ Expression::Atom(atom) => infer_atom(ctx, &atom),
Expression::Call {
name,
args: call_args,
@@ -12,7 +17,7 @@ pub fn infer_type(module: &AatbeModule, expr: &Expression) -> Option<(PrimitiveT
} => {
let args = call_args
.iter()
- .filter_map(|e| infer_type(module, e))
+ .filter_map(|e| infer_type(ctx, e))
.map(|ty| ty.0)
.collect::>();
@@ -20,37 +25,51 @@ pub fn infer_type(module: &AatbeModule, expr: &Expression) -> Option<(PrimitiveT
return None;
}
- let group = module.get_func_group(name)?;
- let func = find_function(group, &args)?;
+ let prefix = |path: &IdentPath| -> Vec {
+ match path {
+ IdentPath::Local(name) => prefix!(call ctx, name.clone()),
+ IdentPath::Module(name) => prefix!(call module ctx, name.clone()),
+ _ => todo!(),
+ }
+ };
- return Some((func.ret_ty().clone(), false));
+ find_function(
+ match ctx.query(Query::FunctionGroup(prefix(name).join("::"))) {
+ QueryResponse::FunctionGroup(Some(group)) => group,
+ QueryResponse::FunctionGroup(None) => todo!("no function found"),
+ _ => unreachable!(),
+ },
+ &args,
+ )
+ .map(|func| Some((func.upgrade().expect("ICE").ret_ty().clone(), false)))
+ .flatten()
}
Expression::RecordInit { record, types, .. } if types.len() == 0 => {
- Some((PrimitiveType::TypeRef(record.clone()), true))
+ Some((Type::TypeRef(record.clone()), true))
}
Expression::RecordInit { record, types, .. } => Some((
- PrimitiveType::GenericTypeRef(record.clone(), types.clone()),
+ Type::GenericTypeRef(record.clone(), types.clone()),
true,
)),
_ => unimplemented!("{:?}", expr),
}
}
-pub fn infer_atom(module: &AatbeModule, atom: &AtomKind) -> Option<(PrimitiveType, bool)> {
+pub fn infer_atom(ctx: &CompilerContext, atom: &AtomKind) -> Option<(Type, bool)> {
match atom {
AtomKind::Integer(_, sz) => Some((sz.clone(), true)),
- AtomKind::Unit => Some((PrimitiveType::Unit, true)),
- AtomKind::StringLiteral(_) => Some((PrimitiveType::Str, true)),
- AtomKind::CharLiteral(_) => Some((PrimitiveType::Char, true)),
- AtomKind::Bool(_) => Some((PrimitiveType::Bool, true)),
- AtomKind::SymbolLiteral(s) => Some((PrimitiveType::Symbol(s.clone()), true)),
+ AtomKind::Unit => Some((Type::Unit, true)),
+ AtomKind::StringLiteral(_) => Some((Type::Str, true)),
+ AtomKind::CharLiteral(_) => Some((Type::Char, true)),
+ AtomKind::Bool(_) => Some((Type::Bool, true)),
+ AtomKind::SymbolLiteral(s) => Some((Type::Symbol(s.clone()), true)),
AtomKind::Array(vals) => {
- let fst = vals.first().and_then(|v| infer_type(module, v));
- if !vals.iter().all(|v| infer_type(module, v) == fst) {
+ let fst = vals.first().and_then(|v| infer_type(ctx, v));
+ if !vals.iter().all(|v| infer_type(ctx, v) == fst) {
None
} else if let Some((ty, constant)) = fst {
Some((
- PrimitiveType::Array {
+ Type::Array {
ty: box ty,
len: vals.len() as u32,
},
@@ -61,12 +80,12 @@ pub fn infer_atom(module: &AatbeModule, atom: &AtomKind) -> Option<(PrimitiveTyp
}
}
AtomKind::Ident(name) => {
- let var = module.get_var(name)?;
-
- Some((var.var_ty().clone(), false))
+ guard!(let QueryResponse::Slot(slot) = ctx.query(Query::Slot(name)) else { unreachable!() });
+ let slot = slot?;
+ Some((slot.var_ty().clone(), false).into())
}
AtomKind::Cast(_, ty) => Some((ty.clone(), false)),
- AtomKind::Parenthesized(box expr) => infer_type(module, expr),
+ AtomKind::Parenthesized(box expr) => infer_type(ctx, expr),
_ => unimplemented!("{:?}", atom),
}
}
diff --git a/comp-be/src/ty/mod.rs b/comp-be/src/ty/mod.rs
index 3c35dbc..b817ead 100644
--- a/comp-be/src/ty/mod.rs
+++ b/comp-be/src/ty/mod.rs
@@ -1,9 +1,9 @@
use crate::{
- codegen::{AatbeModule, ValueTypePair},
+ codegen::{unit::CompilerContext, AatbeModule, ValueTypePair},
fmt::AatbeFmt,
ty::variant::{Variant, VariantType},
};
-use parser::ast::{FloatSize, FunctionType, IntSize, PrimitiveType};
+use parser::ast::{FloatSize, FunctionType, IntSize, Type};
use llvm_sys_wrapper::{LLVMFunctionType, LLVMTypeRef, LLVMValueRef};
@@ -21,7 +21,7 @@ pub use record::Record;
#[derive(Debug)]
pub enum TypeError {
NotFound(String),
- NotFoundPrim(PrimitiveType),
+ NotFoundPrim(Type),
VariantOOB(String, u32),
RecordIndexOOB(String, u32),
NamedOnVariant(String, String),
@@ -32,13 +32,13 @@ pub type TypeResult = Result;
pub enum TypeKind {
RecordType(Record),
- Primitive(PrimitiveType),
+ Primitive(Type),
Typedef(TypedefKind),
}
pub enum TypedefKind {
Opaque(LLVMTypeRef),
- Newtype(LLVMTypeRef, PrimitiveType),
+ Newtype(LLVMTypeRef, Type),
VariantType(VariantType),
}
@@ -65,10 +65,10 @@ impl fmt::Debug for TypedefKind {
}
impl LLVMTyInCtx for TypeKind {
- fn llvm_ty_in_ctx(&self, module: &AatbeModule) -> LLVMTypeRef {
+ fn llvm_ty_in_ctx(&self, ctx: &CompilerContext) -> LLVMTypeRef {
match self {
- TypeKind::RecordType(record) => record.llvm_ty_in_ctx(module),
- TypeKind::Primitive(primitive) => primitive.llvm_ty_in_ctx(module),
+ TypeKind::RecordType(record) => record.llvm_ty_in_ctx(ctx),
+ TypeKind::Primitive(primitive) => primitive.llvm_ty_in_ctx(ctx),
TypeKind::Typedef(TypedefKind::Opaque(ty)) => *ty,
TypeKind::Typedef(TypedefKind::Newtype(ty, _)) => *ty,
TypeKind::Typedef(TypedefKind::VariantType(VariantType { ty, .. })) => *ty,
@@ -136,17 +136,17 @@ impl TypeContext {
}
}
- pub fn get_aggregate_from_prim(&self, prim: &PrimitiveType) -> Option<&dyn Aggregate> {
+ pub fn get_aggregate_from_prim(&self, prim: &Type) -> Option<&dyn Aggregate> {
match prim {
- PrimitiveType::TypeRef(name) => match self.types.get(name) {
+ Type::TypeRef(name) => match self.types.get(name) {
Some(TypeKind::RecordType(record)) => Some(record as &dyn Aggregate),
_ => None,
},
- PrimitiveType::VariantType(name) => match self.get_variant(name) {
+ Type::VariantType(name) => match self.get_variant(name) {
Some(variant) => Some(variant as &dyn Aggregate),
_ => None,
},
- PrimitiveType::Variant { variant, .. } => match self.get_variant(variant) {
+ Type::Variant { variant, .. } => match self.get_variant(variant) {
Some(variant) => Some(variant as &dyn Aggregate),
_ => None,
},
@@ -212,7 +212,8 @@ impl TypeContext {
fields: Vec,
reference: LLVMValueRef,
) -> TypeResult {
- match fields.as_slice() {
+ todo!()
+ /*match fields.as_slice() {
[field] => ty.gep_field(module, field, reference),
[field, subfields @ ..] => {
let field = ty.gep_field(module, field, reference)?;
@@ -224,37 +225,37 @@ impl TypeContext {
self.gep_fields(module, ty, subfields.to_vec(), *field)
}
[] => unreachable!(),
- }
+ }*/
}
}
pub trait LLVMTyInCtx {
- fn llvm_ty_in_ctx(&self, module: &AatbeModule) -> LLVMTypeRef;
+ fn llvm_ty_in_ctx(&self, ctx: &CompilerContext) -> LLVMTypeRef;
}
impl LLVMTyInCtx for FunctionType {
- fn llvm_ty_in_ctx(&self, module: &AatbeModule) -> LLVMTypeRef {
- let ret = self.ret_ty.llvm_ty_in_ctx(module);
+ fn llvm_ty_in_ctx(&self, ctx: &CompilerContext) -> LLVMTypeRef {
+ let ret = self.ret_ty.llvm_ty_in_ctx(ctx);
let mut varargs = false;
let ext = self.ext;
let mut param_types = self
.params
.iter()
.filter_map(|t| match t {
- PrimitiveType::TypeRef(name) => {
+ /*Type::TypeRef(name) => {
Some(module.typectx_ref().get_type(name)?.llvm_ty_in_ctx(module))
- }
- PrimitiveType::Symbol(_) => None,
- PrimitiveType::Unit => None,
- PrimitiveType::Varargs => {
+ }*/
+ Type::Symbol(_) => None,
+ Type::Unit => None,
+ Type::Varargs => {
varargs = true;
None
}
- PrimitiveType::NamedType {
- ty: Some(box PrimitiveType::Slice { ty: box ty }),
+ /*Type::NamedType {
+ ty: Some(box Type::Slice { ty: box ty }),
..
}
- | PrimitiveType::Slice { ty: box ty }
+ | Type::Slice { ty: box ty }
if ext =>
{
Some(
@@ -262,8 +263,8 @@ impl LLVMTyInCtx for FunctionType {
.llvm_context_ref()
.PointerType(ty.llvm_ty_in_ctx(module)),
)
- }
- _ => Some(t.llvm_ty_in_ctx(module)),
+ }*/
+ _ => Some(t.llvm_ty_in_ctx(ctx)),
})
.collect::>();
@@ -278,50 +279,50 @@ impl LLVMTyInCtx for FunctionType {
}
}
-impl LLVMTyInCtx for PrimitiveType {
- fn llvm_ty_in_ctx(&self, module: &AatbeModule) -> LLVMTypeRef {
- let ctx = module.llvm_context_ref();
+impl LLVMTyInCtx for Type {
+ fn llvm_ty_in_ctx(&self, mctx: &CompilerContext) -> LLVMTypeRef {
+ let ctx = mctx.llvm_context;
match self {
- PrimitiveType::Slice { ty } => ctx
+ Type::Slice { ty } => ctx
.StructType(
&mut vec![
- ctx.PointerType(ctx.ArrayType(ty.llvm_ty_in_ctx(module), 0)),
+ ctx.PointerType(ctx.ArrayType(ty.llvm_ty_in_ctx(mctx), 0)),
ctx.Int32Type(),
],
false,
)
.as_ref(),
- PrimitiveType::Array { ty, len } => ctx.ArrayType(ty.llvm_ty_in_ctx(module), *len),
- PrimitiveType::Ref(r) => ctx.PointerType(r.llvm_ty_in_ctx(module)),
- PrimitiveType::Unit => ctx.VoidType(),
- PrimitiveType::Bool => ctx.Int1Type(),
- PrimitiveType::Int(IntSize::Bits8) | PrimitiveType::UInt(IntSize::Bits8) => {
+ Type::Array { ty, len } => ctx.ArrayType(ty.llvm_ty_in_ctx(mctx), *len),
+ Type::Ref(r) => ctx.PointerType(r.llvm_ty_in_ctx(mctx)),
+ Type::Unit => ctx.VoidType(),
+ Type::Bool => ctx.Int1Type(),
+ Type::Int(IntSize::Bits8) | Type::UInt(IntSize::Bits8) => {
ctx.Int8Type()
}
- PrimitiveType::Int(IntSize::Bits16) | PrimitiveType::UInt(IntSize::Bits16) => {
+ Type::Int(IntSize::Bits16) | Type::UInt(IntSize::Bits16) => {
ctx.Int16Type()
}
- PrimitiveType::Int(IntSize::Bits32) | PrimitiveType::UInt(IntSize::Bits32) => {
+ Type::Int(IntSize::Bits32) | Type::UInt(IntSize::Bits32) => {
ctx.Int32Type()
}
- PrimitiveType::Int(IntSize::Bits64) | PrimitiveType::UInt(IntSize::Bits64) => {
+ Type::Int(IntSize::Bits64) | Type::UInt(IntSize::Bits64) => {
ctx.Int64Type()
}
- PrimitiveType::Float(FloatSize::Bits32) => ctx.FloatType(),
- PrimitiveType::Float(FloatSize::Bits64) => ctx.DoubleType(),
- PrimitiveType::Str => ctx.CharPointerType(),
- PrimitiveType::Char => ctx.Int8Type(),
- PrimitiveType::NamedType {
+ Type::Float(FloatSize::Bits32) => ctx.FloatType(),
+ Type::Float(FloatSize::Bits64) => ctx.DoubleType(),
+ Type::Str => ctx.CharPointerType(),
+ Type::Char => ctx.Int8Type(),
+ Type::NamedType {
name: _,
ty: Some(ty),
- } => ty.llvm_ty_in_ctx(module),
- PrimitiveType::TypeRef(name) => module
+ } => ty.llvm_ty_in_ctx(mctx),
+ /*Type::TypeRef(name) => module
.typectx_ref()
.llvm_ty_in_ctx(name)
.expect(format!("Type {} is not declared", name).as_str())
.llvm_ty_in_ctx(module),
- PrimitiveType::GenericTypeRef(name, types) => {
+ Type::GenericTypeRef(name, types) => {
let rec = format!(
"{}[{}]",
name,
@@ -338,17 +339,17 @@ impl LLVMTyInCtx for PrimitiveType {
.expect(format!("Type {} is not declared", rec).as_str())
.llvm_ty_in_ctx(module)
}
- PrimitiveType::Pointer(ty) => match ty {
- box PrimitiveType::Char => ctx.CharPointerType(),
- tr @ box PrimitiveType::TypeRef(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)),
- tr @ box PrimitiveType::UInt(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)),
- tr @ box PrimitiveType::Int(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)),
- box PrimitiveType::Str => ctx.PointerType(ctx.Int8PointerType()),
- box PrimitiveType::Pointer(box ty) => ctx.PointerType(ty.llvm_ty_in_ctx(module)),
+ Type::Pointer(ty) => match ty {
+ box Type::Char => ctx.CharPointerType(),
+ tr @ box Type::TypeRef(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)),
+ tr @ box Type::UInt(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)),
+ tr @ box Type::Int(_) => ctx.PointerType(tr.llvm_ty_in_ctx(module)),
+ box Type::Str => ctx.PointerType(ctx.Int8PointerType()),
+ box Type::Pointer(box ty) => ctx.PointerType(ty.llvm_ty_in_ctx(module)),
_ => panic!("llvm_ty_in_ctx {:?}", ty),
},
- PrimitiveType::Function(ty) => ty.llvm_ty_in_ctx(module),
- PrimitiveType::Newtype(name) => module
+ Type::Function(ty) => ty.llvm_ty_in_ctx(module),
+ Type::Newtype(name) => module
.typectx_ref()
.get_type(&name)
.map(|ty| match ty {
@@ -356,19 +357,17 @@ impl LLVMTyInCtx for PrimitiveType {
_ => unreachable!(),
})
.expect(format!("Cannot find type for {:?}", self).as_ref()),
- PrimitiveType::Variant { variant, .. } => {
+ Type::Variant { variant, .. } => {
module.typectx_ref().get_variant(variant).expect("ICE").ty
}
- PrimitiveType::VariantType(variant) => {
+ Type::VariantType(variant) => {
module
.typectx_ref()
.get_parent_for_variant(variant)
.expect("ICE")
.ty
- }
- PrimitiveType::Box(box val) => module
- .llvm_context_ref()
- .PointerType(val.llvm_ty_in_ctx(module)),
+ }*/
+ Type::Box(box val) => ctx.PointerType(val.llvm_ty_in_ctx(mctx)),
_ => panic!("ICE: llvm_ty_in_ctx {:?}", self),
}
}
diff --git a/comp-be/src/ty/record.rs b/comp-be/src/ty/record.rs
index 7534987..298ec76 100644
--- a/comp-be/src/ty/record.rs
+++ b/comp-be/src/ty/record.rs
@@ -1,8 +1,8 @@
use crate::{
- codegen::{builder::core, AatbeModule, ValueTypePair},
+ codegen::{builder::base, unit::CompilerContext, AatbeModule, ValueTypePair},
ty::{Aggregate, LLVMTyInCtx, TypeError, TypeResult},
};
-use parser::ast::PrimitiveType;
+use parser::ast::Type;
use llvm_sys_wrapper::{LLVMTypeRef, LLVMValueRef, Struct};
use std::collections::HashMap;
@@ -12,15 +12,15 @@ pub struct Record {
name: String,
inner: Struct,
body: HashMap,
- types: HashMap,
+ types: HashMap,
}
impl Record {
- pub fn new(module: &AatbeModule, name: &String, types: &Vec) -> Self {
+ pub fn new(module: &AatbeModule, name: &String, types: &Vec) -> Self {
let mut body = HashMap::new();
let mut types_map = HashMap::new();
types.iter().enumerate().for_each(|(index, ty)| match ty {
- PrimitiveType::NamedType { name, ty: Some(ty) } => {
+ Type::NamedType { name, ty: Some(ty) } => {
body.insert(name.clone(), index as u32);
types_map.insert(index as u32, *ty.clone());
}
@@ -29,22 +29,22 @@ impl Record {
Self {
name: name.clone(),
- inner: Struct::new_with_name(module.llvm_context_ref().as_ref(), name.as_ref()),
+ inner: Struct::new_with_name(module.llvm_context_ref().as_ref(), &name),
body,
types: types_map,
}
}
- pub fn set_body(&self, module: &AatbeModule, types: &Vec) {
+ pub fn set_body(&self, ctx: &CompilerContext, types: &Vec) {
let mut types = types
.iter()
- .map(|ty| ty.llvm_ty_in_ctx(module))
+ .map(|ty| ty.llvm_ty_in_ctx(ctx))
.collect::>();
self.inner.set_body(&mut types, false);
}
- pub fn get_field_index_ty(&self, name: &String) -> Option<(u32, PrimitiveType)> {
+ pub fn get_field_index_ty(&self, name: &String) -> Option<(u32, Type)> {
let idx = self.body.get(name).map(|i| *i);
(idx, self.types.get(&idx?).map(|i| i.clone())).transpose()
}
@@ -57,12 +57,12 @@ impl Record {
impl Aggregate for Record {
fn gep_indexed_field(
&self,
- module: &AatbeModule,
+ ctx: &CompilerContext,
index: u32,
aggregate_ref: LLVMValueRef,
) -> TypeResult {
Ok((
- core::struct_gep(module, aggregate_ref, index),
+ base::struct_gep(ctx, aggregate_ref, index),
self.types
.get(&index)
.ok_or(TypeError::RecordIndexOOB(self.name.clone(), index))?
@@ -73,7 +73,7 @@ impl Aggregate for Record {
fn gep_named_field(
&self,
- module: &AatbeModule,
+ ctx: &CompilerContext,
name: &String,
aggregate_ref: LLVMValueRef,
) -> TypeResult {
@@ -84,7 +84,7 @@ impl Aggregate for Record {
)),
Some(index) => {
let ty = self.types.get(index).cloned().unwrap();
- let gep = core::struct_gep(module, aggregate_ref, *index);
+ let gep = base::struct_gep(ctx, aggregate_ref, *index);
Ok((gep, ty).into())
}
}
@@ -92,19 +92,19 @@ impl Aggregate for Record {
}
pub fn store_named_field(
- module: &AatbeModule,
+ ctx: &CompilerContext,
struct_ref: LLVMValueRef,
rec_name: &String,
rec: &Record,
name: &String,
value: ValueTypePair,
-) -> Result<(), PrimitiveType> {
+) -> Result<(), Type> {
let index = rec
.get_field_index_ty(name)
.expect(format!("Cannot find field {:?} in {:?}\0", name, rec.name).as_str());
- let gep = core::struct_gep_with_name(
- module,
+ let gep = base::struct_gep_with_name(
+ ctx,
struct_ref,
index.0,
format!("{}.{}\0", rec_name, name).as_str(),
@@ -113,13 +113,13 @@ pub fn store_named_field(
if value.prim() != &index.1 {
Err(index.1)
} else {
- module.llvm_builder_ref().build_store(*value, gep);
+ base::store(ctx, *value, gep);
Ok(())
}
}
impl LLVMTyInCtx for &Record {
- fn llvm_ty_in_ctx(&self, _module: &AatbeModule) -> LLVMTypeRef {
+ fn llvm_ty_in_ctx(&self, _ctx: &CompilerContext) -> LLVMTypeRef {
self.inner.as_ref()
}
}
diff --git a/comp-be/src/ty/size.rs b/comp-be/src/ty/size.rs
index c32d663..69e861e 100644
--- a/comp-be/src/ty/size.rs
+++ b/comp-be/src/ty/size.rs
@@ -1,26 +1,26 @@
-use parser::ast::{IntSize, PrimitiveType, TypeKind};
+use parser::ast::{IntSize, Type, TypeKind};
pub trait AatbeSizeOf {
fn size_of(&self) -> usize;
fn smallest(&self) -> usize;
}
-impl AatbeSizeOf for PrimitiveType {
+impl AatbeSizeOf for Type {
fn size_of(&self) -> usize {
match self {
- PrimitiveType::UInt(IntSize::Bits8) => 1,
- PrimitiveType::UInt(IntSize::Bits16) => 2,
- PrimitiveType::UInt(IntSize::Bits32) => 4,
- PrimitiveType::UInt(IntSize::Bits64) => 8,
- PrimitiveType::Int(IntSize::Bits8) => 1,
- PrimitiveType::Int(IntSize::Bits16) => 2,
- PrimitiveType::Int(IntSize::Bits32) => 4,
- PrimitiveType::Int(IntSize::Bits64) => 8,
- PrimitiveType::Str => 8, // TODO: Platform specific pointer size
- PrimitiveType::Pointer(_) => 8, // FIXME: Platform specific pointer size
- PrimitiveType::Box(_) => 8, // FIXME: Platform specific pointer size
- PrimitiveType::Bool => 1,
- PrimitiveType::Char => 1,
+ Type::UInt(IntSize::Bits8) => 1,
+ Type::UInt(IntSize::Bits16) => 2,
+ Type::UInt(IntSize::Bits32) => 4,
+ Type::UInt(IntSize::Bits64) => 8,
+ Type::Int(IntSize::Bits8) => 1,
+ Type::Int(IntSize::Bits16) => 2,
+ Type::Int(IntSize::Bits32) => 4,
+ Type::Int(IntSize::Bits64) => 8,
+ Type::Str => 8, // TODO: Platform specific pointer size
+ Type::Pointer(_) => 8, // FIXME: Platform specific pointer size
+ Type::Box(_) => 8, // FIXME: Platform specific pointer size
+ Type::Bool => 1,
+ Type::Char => 1,
_ => unimplemented!("{:?}", self),
}
}
diff --git a/comp-be/src/ty/variant.rs b/comp-be/src/ty/variant.rs
index 8467bc4..dbb1df4 100644
--- a/comp-be/src/ty/variant.rs
+++ b/comp-be/src/ty/variant.rs
@@ -1,16 +1,16 @@
use crate::{
- codegen::{builder::core, AatbeModule, ValueTypePair},
+ codegen::{builder::base, unit::CompilerContext, ValueTypePair},
ty::{Aggregate, LLVMTyInCtx, TypeError, TypeResult},
};
use llvm_sys_wrapper::{LLVMTypeRef, LLVMValueRef};
-use parser::ast::PrimitiveType;
+use parser::ast::Type;
use std::{collections::HashMap, fmt};
pub struct VariantType {
pub type_name: String,
pub variants: HashMap,
- pub discriminant_type: PrimitiveType,
+ pub discriminant_type: Type,
pub ty: LLVMTypeRef,
}
@@ -21,7 +21,7 @@ impl VariantType {
}
impl LLVMTyInCtx for VariantType {
- fn llvm_ty_in_ctx(&self, _: &AatbeModule) -> LLVMTypeRef {
+ fn llvm_ty_in_ctx(&self, _: &CompilerContext) -> LLVMTypeRef {
self.ty
}
}
@@ -30,13 +30,13 @@ impl LLVMTyInCtx for VariantType {
pub struct Variant {
pub parent_name: String,
pub name: String,
- pub types: Option>,
+ pub types: Option>,
pub ty: LLVMTypeRef,
pub discriminant: u32,
}
impl LLVMTyInCtx for Variant {
- fn llvm_ty_in_ctx(&self, _: &AatbeModule) -> LLVMTypeRef {
+ fn llvm_ty_in_ctx(&self, _: &CompilerContext) -> LLVMTypeRef {
self.ty
}
}
@@ -54,7 +54,7 @@ impl VariantType {
impl Aggregate for Variant {
fn gep_indexed_field(
&self,
- module: &AatbeModule,
+ ctx: &CompilerContext,
index: u32,
aggregate_ref: LLVMValueRef,
) -> TypeResult {
@@ -64,7 +64,7 @@ impl Aggregate for Variant {
Err(TypeError::VariantOOB(self.name.clone(), index))
}
Some(types) => Ok((
- core::struct_gep(module, aggregate_ref, index + 1),
+ base::struct_gep(ctx, aggregate_ref, index + 1),
types[index as usize].clone(),
)
.into()),
@@ -73,7 +73,7 @@ impl Aggregate for Variant {
fn gep_named_field(
&self,
- _module: &AatbeModule,
+ _ctx: &CompilerContext,
name: &String,
_aggregate_ref: LLVMValueRef,
) -> TypeResult {
diff --git a/libc.aat b/libc.aat
new file mode 100644
index 0000000..b20473c
--- /dev/null
+++ b/libc.aat
@@ -0,0 +1 @@
+public extern fn printf str, ... -> i32
\ No newline at end of file
diff --git a/main.aat b/main.aat
index b8a2580..14715fd 100644
--- a/main.aat
+++ b/main.aat
@@ -1,9 +1,28 @@
-fn foo i: i32* -> () = {}
+use libc
-@entry
-fn main() -> () = {
- val i = 32
- val fa = [i]
+module std {
+ public fn println s: str = ::libc::printf "%s\n", s
+ public fn println c: char = ::libc::printf "%c\n", c
+
+ public fn println b: bool =
+ if b then println "true"
+ else println "false"
- foo fa as [i32]
+ public fn println i: i8 = ::libc::printf "%hhi\n", i
+ public fn println i: i16 = ::libc::printf "%hi\n", i
+ public fn println i: i32 = ::libc::printf "%i\n", i
+ public fn println i: i64 = ::libc::printf "%li\n", i
+ public fn println u: u8 = ::libc::printf "%hhu\n", u
+ public fn println u: u16 = ::libc::printf "%hu\n", u
+ public fn println u: u32 = ::libc::printf "%u\n", u
+ public fn println u: u64 = ::libc::printf "%lu\n", u
+ public fn println f: f64 = ::libc::printf "%f\n", f
+ public fn println f: f64 = ::libc::printf "%f\n", f
}
+
+@entry
+fn main () = {
+ std::println false
+ std::println 128u16
+ std::println 'A'
+}
\ No newline at end of file
diff --git a/main.aat.bak b/main.aat.bak
new file mode 100644
index 0000000..b13e9ff
--- /dev/null
+++ b/main.aat.bak
@@ -0,0 +1,26 @@
+module libc {
+ public extern fn printf str, ... -> i32
+}
+
+module std {
+ public fn println s: str -> () = ::libc::printf "%s\n", s
+ public fn println c: char -> () = ::libc::printf "%c\n", c
+
+ public fn println i: i8 -> () = ::libc::printf "%hhi\n", i
+ public fn println i: i16 -> () = ::libc::printf "%hi\n", i
+ public fn println i: i32 -> () = ::libc::printf "%i\n", i
+ public fn println i: i64 -> () = ::libc::printf "%li\n", i
+ public fn println u: u8 -> () = ::libc::printf "%hhu\n", u
+ public fn println u: u16 -> () = ::libc::printf "%hu\n", u
+ public fn println u: u32 -> () = ::libc::printf "%u\n", u
+ public fn println u: u64 -> () = ::libc::printf "%lu\n", u
+ public fn println f: f64 -> () = ::libc::printf "%f\n", f
+ public fn println f: f64 -> () = ::libc::printf "%f\n", f
+}
+
+fn add[I] a: I, b: I -> I = a + b
+
+@entry
+fn main () = {
+ libc::printf "%d\n", add[i32] 10, 8
+}
\ No newline at end of file
diff --git a/parser/src/ast.rs b/parser/src/ast.rs
index 09c063e..aae7a4a 100644
--- a/parser/src/ast.rs
+++ b/parser/src/ast.rs
@@ -1,33 +1,43 @@
use std::fmt;
+type ModPath = Vec;
+
+#[derive(Debug, PartialEq, Clone, Eq, Hash)]
+pub enum IdentPath {
+ Local(String),
+ Module(ModPath),
+ Root(ModPath),
+}
+
#[derive(Debug, PartialEq, Clone)]
pub enum AST {
File(Vec),
Error,
Expr(Expression),
- Import(String),
- Record(String, Option>, Vec),
+ Import(IdentPath),
+ Record(String, Option>, Vec),
Typedef {
name: String,
type_names: Option>,
variants: Option>,
},
Constant {
- ty: PrimitiveType,
+ ty: Type,
export: bool,
value: Box,
},
Global {
- ty: PrimitiveType,
+ ty: Type,
export: bool,
value: Box,
},
+ Module(String, Box),
}
#[derive(Debug, PartialEq, Clone)]
pub enum TypeKind {
- Newtype(PrimitiveType),
- Variant(String, Option>),
+ Newtype(Type),
+ Variant(String, Option>),
}
#[derive(Debug, PartialEq, Clone)]
@@ -37,7 +47,7 @@ pub enum Expression {
Block(Vec),
Ret(Box),
Decl {
- ty: PrimitiveType,
+ ty: Type,
value: Option>,
exterior_bind: BindType,
},
@@ -46,8 +56,8 @@ pub enum Expression {
value: Box,
},
Call {
- name: String,
- types: Vec,
+ name: IdentPath,
+ types: Vec,
args: Vec,
},
Function {
@@ -56,17 +66,17 @@ pub enum Expression {
body: Option>,
attributes: Vec,
type_names: Vec,
- export: bool,
+ public: bool,
},
If {
cond_expr: Box,
then_expr: Box,
+ elseif_exprs: Vec<(Expression, Expression)>,
else_expr: Option>,
- is_expr: bool,
},
RecordInit {
record: String,
- types: Vec,
+ types: Vec,
values: Vec,
},
Loop {
@@ -91,7 +101,7 @@ pub enum BindType {
Constant,
}
-#[derive(Debug, PartialEq, Clone)]
+#[derive(Debug, PartialEq, Clone, Copy)]
pub enum LoopType {
While,
Until,
@@ -100,18 +110,18 @@ pub enum LoopType {
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct FunctionType {
pub ext: bool,
- pub ret_ty: Box,
- pub params: Vec,
+ pub ret_ty: Box,
+ pub params: Vec,
}
-impl From for PrimitiveType {
+impl From for Type {
fn from(func: FunctionType) -> Self {
- PrimitiveType::Function(func)
+ Type::Function(func)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
-pub enum PrimitiveType {
+pub enum Type {
Unit,
Str,
Varargs,
@@ -121,51 +131,41 @@ pub enum PrimitiveType {
UInt(IntSize),
Float(FloatSize),
TypeRef(String),
- GenericTypeRef(String, Vec),
+ GenericTypeRef(String, Vec),
Newtype(String),
VariantType(String),
- Variant {
- parent: String,
- variant: String,
- },
+ Variant { parent: String, variant: String },
Function(FunctionType),
- NamedType {
- name: String,
- ty: Option>,
- },
- Ref(Box),
- Pointer(Box),
- Array {
- ty: Box,
- len: u32,
- },
- Slice {
- ty: Box,
- },
+ NamedType { name: String, ty: Option> },
+ Ref(Box),
+ Pointer(Box),
+ Array { ty: Box, len: u32 },
+ Slice { ty: Box },
Symbol(String),
- Box(Box),
+ Box(Box),
+ Path(ModPath),
}
-impl PrimitiveType {
- pub fn inner(&self) -> &PrimitiveType {
+impl Type {
+ pub fn inner(&self) -> &Type {
match self {
- PrimitiveType::NamedType {
+ Type::NamedType {
name: _,
ty: Some(box ty),
} => ty,
- PrimitiveType::Function(..) => panic!("ICE primty inner {:?}", self),
+ Type::Function(..) => panic!("ICE primty inner {:?}", self),
other => other,
}
}
pub fn ext(&self) -> bool {
match self {
- PrimitiveType::Function(FunctionType {
+ Type::Function(FunctionType {
ext,
ret_ty: _,
params: _,
}) => ext.clone(),
- _ => panic!("ICE PrimitiveType ext {:?}", self),
+ _ => panic!("ICE Type ext {:?}", self),
}
}
}
@@ -175,8 +175,8 @@ pub enum AtomKind {
Unit,
SymbolLiteral(String),
Bool(Boolean),
- Integer(u64, PrimitiveType),
- Floating(f64, PrimitiveType),
+ Integer(u64, Type),
+ Floating(f64, Type),
StringLiteral(String),
CharLiteral(char),
Expr(Box),
@@ -187,7 +187,7 @@ pub enum AtomKind {
Deref(Box),
Ref(Box),
Index(Box, Box),
- Cast(Box, PrimitiveType),
+ Cast(Box, Type),
Array(Vec),
Is(Box, String),
NamedValue { name: String, val: Box },
diff --git a/parser/src/lexer/mod.rs b/parser/src/lexer/mod.rs
index 1a957b9..ecea1da 100644
--- a/parser/src/lexer/mod.rs
+++ b/parser/src/lexer/mod.rs
@@ -239,9 +239,13 @@ impl<'c> Lexer<'c> {
',' => {
symbol!(tokens, Symbol::Comma, pos);
}
- ':' => {
- symbol!(tokens, Symbol::Colon, pos);
- }
+ ':' => match self.chars.peek() {
+ Some(':') => {
+ self.advance();
+ symbol!(tokens, Symbol::Doubly, pos)
+ }
+ _ => symbol!(tokens, Symbol::Colon, pos),
+ },
'%' => {
symbol!(tokens, Symbol::Modulo, pos);
}
@@ -316,9 +320,9 @@ impl<'c> Lexer<'c> {
token!(
tokens,
- Token::keyword(buf.as_ref()).unwrap_or(
- Token::boolean(buf.as_ref()).unwrap_or(
- Token::r#type(buf.as_ref()).unwrap_or(TokenKind::Identifier(buf)),
+ Token::keyword(&buf).unwrap_or(
+ Token::boolean(&buf).unwrap_or(
+ Token::r#type(&buf).unwrap_or(TokenKind::Identifier(buf)),
),
),
pos
@@ -351,9 +355,10 @@ impl<'c> Lexer<'c> {
};
}
if buf.contains(".") {
- TokenKind::FloatLiteral(f64::from_str(&buf).expect(
- format!("{} is not a floating point literal", buf).as_ref(),
- ))
+ TokenKind::FloatLiteral(
+ f64::from_str(&buf)
+ .expect(&format!("{} is not a floating point literal", buf)),
+ )
} else {
TokenKind::IntLiteral(
u64::from_str_radix(&buf, 10).expect("Lexer died @digits -> u64"),
@@ -377,9 +382,10 @@ impl<'c> Lexer<'c> {
token!(
tokens,
if buf.contains(".") {
- TokenKind::FloatLiteral(f64::from_str(&buf).expect(
- format!("{} is not a floating point literal", buf).as_ref(),
- ))
+ TokenKind::FloatLiteral(
+ f64::from_str(&buf)
+ .expect(&format!("{} is not a floating point literal", buf)),
+ )
} else {
TokenKind::IntLiteral(
u64::from_str_radix(&buf, 10).expect("Lexer died @digits -> u64"),
diff --git a/parser/src/lexer/tests.rs b/parser/src/lexer/tests.rs
index 65a689a..230cd1f 100644
--- a/parser/src/lexer/tests.rs
+++ b/parser/src/lexer/tests.rs
@@ -1,7 +1,7 @@
#[cfg(test)]
mod lexer_tests {
use crate::lexer::{
- token::{Boolean, Keyword, Type},
+ token::{Boolean, Keyword, TokenType},
Lexer, Symbol, TokenKind,
};
#[test]
@@ -150,7 +150,7 @@ mod lexer_tests {
#[test]
fn keyword_identifier() {
let mut lexer = Lexer::new(
- "fn extern var val if else use true false main record.test bool rec global ret while until type is exp",
+ "fn extern var val if else use true false main record.test bool rec global ret while until type is public module",
);
let mut tokens = lexer.lex().into_iter();
@@ -194,11 +194,13 @@ mod lexer_tests {
sep!(tokens);
assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Until));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Type));
+ assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::TokenType));
sep!(tokens);
assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Is));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Exp));
+ assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Public));
+ sep!(tokens);
+ assert_eq!(tokens.next().unwrap().kw(), Some(Keyword::Module));
}
#[test]
@@ -206,26 +208,26 @@ mod lexer_tests {
let mut lexer = Lexer::new("str i8 i16 i32 i64 u8 u16 u32 u64 f32 f64");
let mut tokens = lexer.lex().into_iter();
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::Str));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::Str));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::I8));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::I8));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::I16));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::I16));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::I32));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::I32));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::I64));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::I64));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::U8));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::U8));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::U16));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::U16));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::U32));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::U32));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::U64));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::U64));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::F32));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::F32));
sep!(tokens);
- assert_eq!(tokens.next().unwrap().ty(), Some(Type::F64));
+ assert_eq!(tokens.next().unwrap().ty(), Some(TokenType::F64));
}
}
diff --git a/parser/src/lexer/token.rs b/parser/src/lexer/token.rs
index 99b0711..f563987 100644
--- a/parser/src/lexer/token.rs
+++ b/parser/src/lexer/token.rs
@@ -18,7 +18,7 @@ pub enum TokenKind {
BooleanLiteral(Boolean),
Identifier(String),
Keyword(Keyword),
- Type(Type),
+ TokenType(TokenType),
StringLiteral(String),
CharLiteral(char),
EOL,
@@ -60,6 +60,7 @@ pub enum Symbol {
Dot,
DoDot,
GoDot,
+ Doubly,
}
impl From for String {
@@ -82,6 +83,7 @@ impl From for String {
Symbol::And => String::from("&&"),
Symbol::Xor => String::from("^"),
Symbol::Modulo => String::from("%"),
+ Symbol::Doubly => String::from("::"),
_ => panic!("Symbol to str {:?}", sym),
}
}
@@ -111,13 +113,14 @@ pub enum Keyword {
Ret,
While,
Until,
- Type,
+ TokenType,
Is,
- Exp,
+ Public,
+ Module,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
-pub enum Type {
+pub enum TokenType {
Char,
Str,
I8,
@@ -160,7 +163,7 @@ impl Token {
}
to_tok!(keyword, Keyword, Keyword);
to_tok!(boolean, BooleanLiteral, Boolean);
- to_tok!(r#type, Type, Type);
+ to_tok!(r#type, TokenType, TokenType);
pub fn op(&self) -> Option {
if let TokenKind::Symbol(sym) = self.kind {
return match sym {
@@ -202,13 +205,13 @@ impl Token {
from_tok!(int, IntLiteral, u64);
from_tok!(float, FloatLiteral, f64);
from_tok!(ident, Identifier, String);
- from_tok!(ty, Type, Type);
+ from_tok!(ty, TokenType, TokenType);
from_tok!(st, StringLiteral, String);
from_tok!(comm, Comment, String);
from_tok!(ch, CharLiteral, char);
}
-impl FromStr for Type {
+impl FromStr for TokenType {
type Err = ();
fn from_str(s: &str) -> Result {
match s {
@@ -249,9 +252,10 @@ impl FromStr for Keyword {
"ret" => Ok(Self::Ret),
"while" => Ok(Self::While),
"until" => Ok(Self::Until),
- "type" => Ok(Self::Type),
+ "type" => Ok(Self::TokenType),
"is" => Ok(Self::Is),
- "exp" => Ok(Self::Exp),
+ "public" => Ok(Self::Public),
+ "module" => Ok(Self::Module),
_ => Err(()),
}
}
diff --git a/parser/src/lib.rs b/parser/src/lib.rs
index 582947c..2486629 100644
--- a/parser/src/lib.rs
+++ b/parser/src/lib.rs
@@ -8,10 +8,10 @@ pub mod parser;
mod tests;
use crate::{
- ast::{Expression, FloatSize, IntSize, PrimitiveType, TypeKind, AST},
+ ast::{Expression, FloatSize, IntSize, Type, TypeKind, AST},
lexer::{
token,
- token::{Keyword, Symbol, Type},
+ token::{Keyword, Symbol, TokenType},
},
parser::{ParseError, ParseResult, Parser},
};
@@ -20,19 +20,19 @@ use ast::FunctionType;
use std::path::PathBuf;
impl Parser {
- fn parse_type(&mut self) -> ParseResult {
+ fn parse_type(&mut self) -> ParseResult {
let token = self.next();
if let Some(tok) = token {
match tok.sym() {
- Some(Symbol::Colon) => Some(PrimitiveType::Symbol(ident!(res self)?)),
- Some(Symbol::Unit) => Some(PrimitiveType::Unit),
- Some(Symbol::GoDot) => Some(PrimitiveType::Varargs),
+ Some(Symbol::Colon) => Some(Type::Symbol(ident!(res self)?)),
+ Some(Symbol::Unit) => Some(Type::Unit),
+ Some(Symbol::GoDot) => Some(Type::Varargs),
Some(Symbol::Ampersand) => capture!(res parse_type, self)
.ok()
- .and_then(|ty| Some(PrimitiveType::Ref(box ty))),
+ .and_then(|ty| Some(Type::Ref(box ty))),
Some(Symbol::At) => capture!(res parse_type, self)
.ok()
- .and_then(|ty| Some(PrimitiveType::Box(box ty))),
+ .and_then(|ty| Some(Type::Box(box ty))),
Some(Symbol::LBracket) => capture!(res parse_type, self).ok().and_then(|ty| {
let len = if sym!(bool Comma, self) {
self.peek().and_then(|tok| tok.int()).map(|len| len as u32)
@@ -44,14 +44,14 @@ impl Parser {
}
sym!(RBracket, self);
Some(match len {
- None => PrimitiveType::Slice { ty: box ty },
- Some(len) => PrimitiveType::Array { ty: box ty, len },
+ None => Type::Slice { ty: box ty },
+ Some(len) => Type::Array { ty: box ty, len },
})
}),
_ => None,
}
.or_else(|| match tok.kw() {
- Some(Keyword::Bool) => Some(PrimitiveType::Bool),
+ Some(Keyword::Bool) => Some(Type::Bool),
_ => None,
})
.or_else(|| match tok.ident() {
@@ -62,26 +62,44 @@ impl Parser {
.parse_type_list()
.expect(format!("Expected type list at {}", tyref).as_str());
sym!(RBracket, self);
- Some(PrimitiveType::GenericTypeRef(tyref, types))
+ Some(Type::GenericTypeRef(tyref, types))
} else {
- Some(PrimitiveType::TypeRef(tyref))
+ if matches!(self.peek_symbol(Symbol::Doubly), Some(true)) {
+ let mut res = vec![tyref];
+ self.next();
+ loop {
+ match self.peek_ident() {
+ None => break,
+ Some(ty) => {
+ self.next();
+ res.push(ty);
+ if matches!(self.peek_symbol(Symbol::Doubly), Some(true)) {
+ self.next();
+ }
+ }
+ }
+ }
+ Some(Type::Path(res))
+ } else {
+ Some(Type::TypeRef(tyref))
+ }
}
}
None => None,
})
.or_else(|| match tok.ty() {
- Some(Type::Str) => Some(PrimitiveType::Str),
- Some(Type::Char) => Some(PrimitiveType::Char),
- Some(Type::I8) => Some(PrimitiveType::Int(IntSize::Bits8)),
- Some(Type::I16) => Some(PrimitiveType::Int(IntSize::Bits16)),
- Some(Type::I32) => Some(PrimitiveType::Int(IntSize::Bits32)),
- Some(Type::I64) => Some(PrimitiveType::Int(IntSize::Bits64)),
- Some(Type::U8) => Some(PrimitiveType::UInt(IntSize::Bits8)),
- Some(Type::U16) => Some(PrimitiveType::UInt(IntSize::Bits16)),
- Some(Type::U32) => Some(PrimitiveType::UInt(IntSize::Bits32)),
- Some(Type::U64) => Some(PrimitiveType::UInt(IntSize::Bits64)),
- Some(Type::F32) => Some(PrimitiveType::Float(FloatSize::Bits32)),
- Some(Type::F64) => Some(PrimitiveType::Float(FloatSize::Bits64)),
+ Some(TokenType::Str) => Some(Type::Str),
+ Some(TokenType::Char) => Some(Type::Char),
+ Some(TokenType::I8) => Some(Type::Int(IntSize::Bits8)),
+ Some(TokenType::I16) => Some(Type::Int(IntSize::Bits16)),
+ Some(TokenType::I32) => Some(Type::Int(IntSize::Bits32)),
+ Some(TokenType::I64) => Some(Type::Int(IntSize::Bits64)),
+ Some(TokenType::U8) => Some(Type::UInt(IntSize::Bits8)),
+ Some(TokenType::U16) => Some(Type::UInt(IntSize::Bits16)),
+ Some(TokenType::U32) => Some(Type::UInt(IntSize::Bits32)),
+ Some(TokenType::U64) => Some(Type::UInt(IntSize::Bits64)),
+ Some(TokenType::F32) => Some(Type::Float(FloatSize::Bits32)),
+ Some(TokenType::F64) => Some(Type::Float(FloatSize::Bits64)),
_ => None,
})
} else {
@@ -90,14 +108,14 @@ impl Parser {
.and_then(|ty| {
let mut ty = ty;
while sym!(bool Star, self) {
- ty = PrimitiveType::Pointer(box ty);
+ ty = Type::Pointer(box ty);
}
Some(ty)
})
.ok_or(ParseError::ExpectedType)
}
- fn parse_named_type(&mut self) -> ParseResult {
+ fn parse_named_type(&mut self) -> ParseResult {
let name = ident!(required self);
if sym!(bool Comma, self)
| sym!(bool Arrow, self)
@@ -111,7 +129,7 @@ impl Parser {
} else {
None
};
- Ok(PrimitiveType::NamedType { name, ty })
+ Ok(Type::NamedType { name, ty })
}
fn parse_attribute(&mut self) -> Option {
@@ -121,20 +139,13 @@ impl Parser {
fn parse_use(&mut self) -> ParseResult {
kw!(Use, self);
- if let Some(path) = self.peek_str() {
- self.next();
- let pb = PathBuf::from(path);
+ let path = path!(module self);
- Ok(AST::Import(
- pb.to_str().expect("ICE parse_use pb.to_str").to_string(),
- ))
- } else {
- Err(ParseError::ExpectedPath)
- }
+ Ok(AST::Import(path))
}
- fn parse_type_list(&mut self) -> ParseResult> {
+ fn parse_type_list(&mut self) -> ParseResult> {
let mut params = vec![];
loop {
@@ -151,7 +162,7 @@ impl Parser {
Ok(params)
}
- fn parse_free_type_list(&mut self) -> ParseResult> {
+ fn parse_free_type_list(&mut self) -> ParseResult> {
let mut params = vec![];
loop {
@@ -190,7 +201,7 @@ impl Parser {
};
let fields = if sym!(bool Unit, self) {
- vec![PrimitiveType::Unit]
+ vec![Type::Unit]
} else {
sym!(required LParen, self);
let fields = self
@@ -204,7 +215,7 @@ impl Parser {
}
fn parse_const_global(&mut self) -> ParseResult {
- let export = kw!(bool Exp, self);
+ let export = kw!(bool Public, self);
let cons = kw!(bool Const, self);
let glob = kw!(bool Global, self);
@@ -225,7 +236,7 @@ impl Parser {
}
fn parse_typedef(&mut self) -> ParseResult {
- kw!(Type, self);
+ kw!(TokenType, self);
let name = ident!(res self)?;
let type_names = if sym!(bool LBracket, self) {
@@ -242,7 +253,7 @@ impl Parser {
Some(if sym!(bool Pipe, self) {
let mut variants = vec![];
- if let PrimitiveType::TypeRef(name) = ty {
+ if let Type::TypeRef(name) = ty {
self.variants.push(name.clone());
variants.push(TypeKind::Variant(name, vars));
} else {
@@ -264,7 +275,7 @@ impl Parser {
variants
} else {
if vars.is_some() {
- if let PrimitiveType::TypeRef(name) = ty {
+ if let Type::TypeRef(name) = ty {
vec![TypeKind::Variant(name, vars)]
} else {
return Err(ParseError::ExpectedIdent);
@@ -294,7 +305,7 @@ impl Parser {
}
}
- let export = kw!(bool Exp, self);
+ let public = kw!(bool Public, self);
let ext = kw!(bool Extern, self);
kw!(Fn, self);
let name = ident!(required self);
@@ -314,7 +325,7 @@ impl Parser {
let ret_ty = box if sym!(bool Arrow, self) {
capture!(res parse_type, self)?
} else {
- PrimitiveType::Unit
+ Type::Unit
};
let mut body = None;
@@ -327,7 +338,7 @@ impl Parser {
attributes,
body,
type_names,
- export,
+ public,
ty: FunctionType {
ext,
ret_ty,
@@ -335,4 +346,20 @@ impl Parser {
},
}))
}
+
+ fn parse_module(&mut self) -> ParseResult {
+ if kw!(bool Module, self) {
+ let name = ident!(required self);
+ sym!(required LCurly, self);
+ if sym!(bool RCurly, self) {
+ Ok(AST::Module(name, box AST::File(vec![])))
+ } else {
+ let res = Ok(AST::Module(name, box self.parse()?));
+ sym!(required RCurly, self);
+ res
+ }
+ } else {
+ Err(ParseError::Continue)
+ }
+ }
}
diff --git a/parser/src/parser/atom.rs b/parser/src/parser/atom.rs
index 4d65fb7..22e898f 100644
--- a/parser/src/parser/atom.rs
+++ b/parser/src/parser/atom.rs
@@ -1,8 +1,8 @@
use crate::{
- ast::{AtomKind, Boolean, FloatSize, IntSize, PrimitiveType},
+ ast::{AtomKind, Boolean, FloatSize, IntSize, Type},
parser::{ParseError, ParseResult, Parser},
token,
- token::{Keyword, Symbol, Type},
+ token::{Keyword, Symbol, TokenType},
};
impl Parser {
@@ -21,22 +21,22 @@ impl Parser {
}
fn parse_number(&mut self) -> Option {
- fn parse_number_type(parser: &mut Parser) -> Option