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,
+ }
+ }
}