diff --git a/docs/examples/hello_world.srn b/docs/examples/hello_world.srn index 5a75c30..f3f9083 100644 --- a/docs/examples/hello_world.srn +++ b/docs/examples/hello_world.srn @@ -1,3 +1,3 @@ -(def a 4) +(def a true) ;; (defn hello! (name) ;; (println "Hello %s" name)) diff --git a/src/ast.rs b/src/ast.rs index 10b22cc..b7a35fd 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -58,7 +58,7 @@ impl Expr { impl Expression for Expr { fn eval() {} - fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx> { + fn code_gen<'ctx, 'val: 'ctx>(&self, compiler: &'ctx mut Compiler<'val>) -> ExprResult<'val> { match self { Expr::Sym(s) => s.code_gen(compiler), Expr::Cons(s) => s.code_gen(compiler), diff --git a/src/builtins/def.rs b/src/builtins/def.rs index 0d4e739..f3bcc21 100644 --- a/src/builtins/def.rs +++ b/src/builtins/def.rs @@ -14,11 +14,13 @@ * 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::collections::core::Seq; -use crate::types::{ExprResult, List}; +use crate::types::{ExprResult, Expression, List}; +use crate::values::Value; -pub fn def<'a>(compiler: &'a Compiler, args: List) -> ExprResult<'a> { +pub fn def<'ctx, 'val: 'ctx>(compiler: &'ctx mut Compiler<'val>, args: List) -> ExprResult<'val> { // TODO: We need to support docstrings for def if args.length() != 2 { // TODO: Raise a meaningful error by including the location @@ -28,12 +30,24 @@ pub fn def<'a>(compiler: &'a Compiler, args: List) -> ExprResult<'a> { )); } - //let def_ = &args.first;1 - let name = args.first(); - let value = args.rest().first(); + let sym = match args.first() { + Some(e) => match e { + Expr::Sym(e) => e, + _ => return Err("First argument of 'def' has to be a symbol".to_string()), + }, + _ => return Err("First argument of 'def' has to be a symbol".to_string()), + }; - println!("<<<< {:?} \n {:?}", name, value); - // TODO: make sure that `def_` is a symbol and its name is "def" + let value = match args.rest().first() { + Some(e) => { + let generated_code = e.code_gen(compiler); + Value::new(Some(sym.name.clone()), e, generated_code) + } + _ => return Err("Missing the second arugment for 'def'.".to_string()), + }; - Err("Is not completed".to_string()) + compiler + .current_ns() + .unwrap() + .define(sym.name.clone(), value, true) } diff --git a/src/compiler.rs b/src/compiler.rs index 196e69c..62849ec 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -16,7 +16,7 @@ */ use inkwell::builder::Builder; use inkwell::context::Context; -use inkwell::passes::PassManager; +//use inkwell::passes::PassManager; use inkwell::values::{AnyValueEnum, BasicValue, FloatValue, FunctionValue, PointerValue}; use crate::namespace::Namespace; @@ -35,9 +35,9 @@ pub struct Compiler<'ctx> { // /// two entries in this hashmap. One would be the ns name itself which // /// is `abc.xyz` in this case and the otherone would be // /// `/path/to/abc/xyz.srn` file that contains the ns. - pub namespaces: HashMap<&'ctx str, Namespace<'ctx>>, + pub namespaces: HashMap>, //pub fpm: &'a PassManager>, - current_ns_name: Option<&'ctx str>, + current_ns_name: Option, } impl<'ctx> Compiler<'ctx> { @@ -64,24 +64,28 @@ impl<'ctx> Compiler<'ctx> { } } - pub fn create_ns(&mut self, ns_name: &'ctx str) { - self.namespaces - .insert(ns_name, Namespace::new(&self.context, ns_name)); + pub fn create_ns(&mut self, ns_name: String, source_file: Option<&'ctx str>) { + self.namespaces.insert( + ns_name.clone(), + Namespace::new(&self.context, ns_name, None), + ); } - pub fn set_current_ns(&mut self, ns_name: &'ctx str) { + pub fn set_current_ns(&mut self, ns_name: String) { self.current_ns_name = Some(ns_name); } #[inline] - pub fn current_ns(&self) -> Option<&Namespace<'ctx>> { - let ns = self.current_ns_name?; - self.namespaces.get(ns).map(|x| x) + pub fn current_ns(&mut self) -> Option<&mut Namespace<'ctx>> { + match &self.current_ns_name { + Some(ns) => self.namespaces.get_mut(ns).map(|x| x), + _ => None, + } } /// Returns the `FunctionValue` representing the function being compiled. #[inline] - pub fn current_fn(&self) -> FunctionValue<'ctx> { + pub fn current_fn(&mut self) -> FunctionValue<'ctx> { self.current_ns().unwrap().current_fn() } @@ -106,16 +110,16 @@ pub fn create_context() -> Context { /// Compiles the given `ast` using the given `compiler` into /// LLVM IR. -pub fn compile<'ctx>( - compiler: &'ctx Compiler, +pub fn compile<'ctx, 'val: 'ctx>( + compiler: &'ctx mut Compiler<'val>, ast: Vec, -) -> Vec, String>> { +) -> Vec, String>> { match compiler.current_ns() { Some(ns) => ns, None => panic!("Current namespace is not set."), }; - let mut generated_code = vec![]; + let mut generated_code: Vec, String>> = vec![]; for expr in &ast { generated_code.push(expr.code_gen(compiler)); diff --git a/src/main.rs b/src/main.rs index fd8f107..aa4d4f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,8 +39,8 @@ fn main() -> io::Result<()> { let context = compiler::create_context(); let mut compiler = compiler::Compiler::new(&context); - compiler.create_ns("user"); - compiler.set_current_ns("user"); + compiler.create_ns("user".to_string(), None); + compiler.set_current_ns("user".to_string()); if let Some(input) = args.value_of("INPUT") { let mut f = File::open(input)?; @@ -51,7 +51,7 @@ fn main() -> io::Result<()> { Ok(v) => { println!("AST: {:#?}", v); - let g = compiler::compile(&compiler, v); + let g = compiler::compile(&mut compiler, v); println!("GEN: {:?}", g) } Err(e) => println!(">> error {:?}", e), diff --git a/src/namespace.rs b/src/namespace.rs index 6c91118..0c32ff4 100644 --- a/src/namespace.rs +++ b/src/namespace.rs @@ -15,9 +15,12 @@ * along with this program. If not, see . */ use crate::scope::Scope; +use crate::types::ExprResult; +use crate::values::Value; use inkwell::context::Context; use inkwell::module::Module; -use inkwell::values::FunctionValue; +use inkwell::types::{AnyTypeEnum, BasicType, FunctionType}; +use inkwell::values::{AnyValueEnum, FunctionValue}; pub struct Namespace<'ctx> { /// Each namespace in serene contains it's own LLVM module. You can @@ -36,9 +39,17 @@ pub struct Namespace<'ctx> { } impl<'ctx> Namespace<'ctx> { - pub fn new(context: &'ctx Context, name: &str) -> Namespace<'ctx> { + pub fn new( + context: &'ctx Context, + name: String, + source_file: Option<&'ctx str>, + ) -> Namespace<'ctx> { + let module = context.create_module(&name); + + module.set_source_file_name(source_file.unwrap_or(&name)); + Namespace { - module: context.create_module(&name), + module, //scope: Scope::new(None), current_fn_opt: None, scope: Scope::new(None), @@ -56,4 +67,58 @@ impl<'ctx> Namespace<'ctx> { pub fn current_fn(&self) -> FunctionValue<'ctx> { self.current_fn_opt.unwrap() } + + fn define_function( + &self, + name: String, + value: Value<'ctx>, + public: bool, + f: FunctionType<'ctx>, + ) -> ExprResult<'ctx> { + Err("NotImpelemnted".to_string()) + } + + fn define_value( + &mut self, + name: String, + value: Value<'ctx>, + public: bool, + t: impl BasicType<'ctx>, + ) -> ExprResult<'ctx> { + let c = self.module.add_global(t, None, &name); + match value.llvm_value { + Ok(v) => { + match v { + AnyValueEnum::ArrayValue(a) => c.set_initializer(&a), + AnyValueEnum::IntValue(i) => c.set_initializer(&i), + AnyValueEnum::FloatValue(f) => c.set_initializer(&f), + AnyValueEnum::PointerValue(p) => c.set_initializer(&p), + AnyValueEnum::StructValue(s) => c.set_initializer(&s), + AnyValueEnum::VectorValue(v) => c.set_initializer(&v), + _ => panic!("It shoudn't happen!!!"), + }; + + self.scope.insert(&name, value, public); + Ok(v) + } + + Err(e) => Err(e), + } + } + + pub fn define(&mut self, name: String, value: Value<'ctx>, public: bool) -> ExprResult<'ctx> { + match value.llvm_value { + Ok(r) => match r.get_type() { + AnyTypeEnum::FunctionType(f) => self.define_function(name, value, public, f), + AnyTypeEnum::IntType(i) => self.define_value(name, value, public, i), + AnyTypeEnum::ArrayType(a) => self.define_value(name, value, public, a), + AnyTypeEnum::FloatType(f) => self.define_value(name, value, public, f), + AnyTypeEnum::PointerType(p) => self.define_value(name, value, public, p), + AnyTypeEnum::StructType(s) => self.define_value(name, value, public, s), + AnyTypeEnum::VectorType(v) => self.define_value(name, value, public, v), + _ => Err(format!("Data type '{:?}' is not supported", r.get_type())), + }, + Err(e) => Err(e), + } + } } diff --git a/src/types/collections/list.rs b/src/types/collections/list.rs index 74138c3..3133bcd 100644 --- a/src/types/collections/list.rs +++ b/src/types/collections/list.rs @@ -47,10 +47,11 @@ impl List { impl Expression for List { fn eval() {} - fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx> { + fn code_gen<'ctx, 'val: 'ctx>(&self, compiler: &'ctx mut Compiler<'val>) -> ExprResult<'val> { match self.first() { Some(e) => match e { Expr::Sym(s) if s.is_def() => def(compiler, self.rest()), + _ => Err("Not implemented on list".to_string()), }, diff --git a/src/types/core.rs b/src/types/core.rs index a404898..bbf171e 100644 --- a/src/types/core.rs +++ b/src/types/core.rs @@ -15,11 +15,13 @@ * along with this program. If not, see . */ use crate::compiler::Compiler; -use inkwell::values::AnyValueEnum; +use inkwell::values::{AnyValue, AnyValueEnum}; -pub type ExprResult<'a> = Result, String>; +type ExprResultBase<'a, T: AnyValue<'a>> = Result; + +pub type ExprResult<'a> = ExprResultBase<'a, AnyValueEnum<'a>>; pub trait Expression { fn eval(); - fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx>; + fn code_gen<'ctx, 'val: 'ctx>(&self, compiler: &'ctx mut Compiler<'val>) -> ExprResult<'val>; } diff --git a/src/types/number.rs b/src/types/number.rs index d4ddb80..95340fd 100644 --- a/src/types/number.rs +++ b/src/types/number.rs @@ -46,7 +46,7 @@ impl Eq for Number {} impl Expression for Number { fn eval() {} - fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx> { + fn code_gen<'ctx, 'val: 'ctx>(&self, compiler: &'ctx mut Compiler<'val>) -> ExprResult<'val> { Err("Not implemented on numbers".to_string()) } } diff --git a/src/types/symbol.rs b/src/types/symbol.rs index b8e9557..4613af4 100644 --- a/src/types/symbol.rs +++ b/src/types/symbol.rs @@ -16,6 +16,7 @@ */ use crate::compiler::Compiler; use crate::types::core::{ExprResult, Expression}; +use inkwell::types::IntType; use inkwell::values::AnyValueEnum; #[derive(Debug, Clone)] @@ -33,8 +34,8 @@ impl Eq for Symbol {} impl Expression for Symbol { fn eval() {} - fn code_gen<'ctx>(&self, compiler: &'ctx Compiler) -> ExprResult<'ctx> { - let bool_t = compiler.context.bool_type(); + fn code_gen<'ctx, 'val: 'ctx>(&self, compiler: &'ctx mut Compiler<'val>) -> ExprResult<'val> { + let bool_t: IntType<'val> = compiler.context.bool_type(); if self.name == "true" { Ok(AnyValueEnum::IntValue(bool_t.const_int(1, false))) } else if self.name == "false" { diff --git a/src/values.rs b/src/values.rs index 4b5c32e..8b0fdb8 100644 --- a/src/values.rs +++ b/src/values.rs @@ -15,10 +15,21 @@ * along with this program. If not, see . */ use crate::ast::Expr; -use inkwell::values::AnyValueEnum; +use crate::types::ExprResult; +#[derive(Debug, Eq, PartialEq, Clone)] pub struct Value<'a> { - llvm_id: Option<&'a str>, - lllvm_value: AnyValueEnum<'a>, - expr: &'a Expr, + pub llvm_id: Option, + pub llvm_value: ExprResult<'a>, + pub expr: Expr, +} + +impl<'a> Value<'a> { + pub fn new(name: Option, expr: Expr, value: ExprResult<'a>) -> Value { + Value { + llvm_id: name, + llvm_value: value, + expr: expr, + } + } }