diff --git a/src/ast.rs b/src/ast.rs index 06733d0..57eba9c 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -24,14 +24,14 @@ pub enum Expr { Num(Number), Comment, Error(String), - Cons(List), + Cons(Box), Nil, NoMatch, } impl Expr { pub fn make_list(first: Expr, rest: Expr) -> Expr { - Expr::Cons(List::::new(Box::new(first), Box::new(rest))) + Expr::Cons(Box::new(List::new(first, rest))) } pub fn make_symbol(v: String) -> Expr { diff --git a/src/builtins/def.rs b/src/builtins/def.rs index 19e61d2..71daa17 100644 --- a/src/builtins/def.rs +++ b/src/builtins/def.rs @@ -14,10 +14,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -use crate::ast::Expr; use crate::compiler::Compiler; use crate::types::{ExprResult, List}; -pub fn def<'a>(compiler: &'a Compiler, args: &'a List) -> ExprResult<'a> { +pub fn def<'a>(compiler: &'a Compiler, args: &'a List) -> ExprResult<'a> { Err("Not implemented".to_string()) } diff --git a/src/main.rs b/src/main.rs index 222331f..75d3f68 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,7 +49,7 @@ fn main() -> io::Result<()> { f.read_to_string(&mut buf)?; match reader::read_string(&buf) { Ok(v) => { - println!("AST: {:?}", v); + println!("AST: {:#?}", v); let g = compiler::compile(&compiler, v); println!("GEN: {:?}", g) } diff --git a/src/namespace.rs b/src/namespace.rs index 42ab358..6c91118 100644 --- a/src/namespace.rs +++ b/src/namespace.rs @@ -24,10 +24,15 @@ pub struct Namespace<'ctx> { /// think of modules as compilation units. Object files if you prefer. /// This way we should be able to hot swap the namespaces. pub module: Module<'ctx>, + + /// Root scope of the namespace scope: Scope<'ctx>, - // The option of the current function being compiled + /// The option of the current function being compiled current_fn_opt: Option>, + // Current scope of the namespace, for example when we're processing + // a let form, this field would refer to the scope of that let form. + //current_scope_opt: Option>, } impl<'ctx> Namespace<'ctx> { @@ -37,6 +42,7 @@ impl<'ctx> Namespace<'ctx> { //scope: Scope::new(None), current_fn_opt: None, scope: Scope::new(None), + //current_scope_opt: None, } } /// Get a defined function given its name. diff --git a/src/types/list.rs b/src/types/list.rs index dc44c53..fa0786f 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -13,23 +13,43 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . -*/ + */ +use crate::ast::Expr; use crate::compiler::Compiler; use crate::types::core::{ExprResult, Expression}; #[derive(Debug, Eq, PartialEq, Clone)] -pub struct List { - first: Box, - rest: Box, +pub struct List { + first: Expr, + rest: Expr, + length: u64, } -impl List { - pub fn new(first: Box, rest: Box) -> List { - List { first, rest } +impl List { + pub fn new(first: Expr, rest: Expr) -> List { + // The order of field definition is important here. + // If we move the `length` after `rest` we're going + // to break the ownership rule of rust because `rest: rest` + // is going to move it to the new list and we can not + // borrow it afterward. + List { + length: match &rest { + Expr::Cons(v) => v.length + 1, + _ => { + if let Expr::Nil = first { + 0 + } else { + 1 + } + } + }, + first, + rest, + } } } -impl Expression for List { +impl Expression for List { fn eval() {} fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx> { Err("Not implemented on list".to_string())