Create 'def' special form to define global value ( not functions at the moment )
This commit is contained in:
parent
fe1724ce22
commit
40bcb3b16c
|
@ -1,3 +1,3 @@
|
|||
(def a 4)
|
||||
(def a true)
|
||||
;; (defn hello! (name)
|
||||
;; (println "Hello %s" name))
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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<String, Namespace<'ctx>>,
|
||||
//pub fpm: &'a PassManager<FunctionValue<'ctx>>,
|
||||
current_ns_name: Option<&'ctx str>,
|
||||
current_ns_name: Option<String>,
|
||||
}
|
||||
|
||||
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<impl Expression>,
|
||||
) -> Vec<Result<AnyValueEnum<'ctx>, String>> {
|
||||
) -> Vec<Result<AnyValueEnum<'val>, 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<Result<AnyValueEnum<'val>, String>> = vec![];
|
||||
|
||||
for expr in &ast {
|
||||
generated_code.push(expr.code_gen(compiler));
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
},
|
||||
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
use crate::compiler::Compiler;
|
||||
use inkwell::values::AnyValueEnum;
|
||||
use inkwell::values::{AnyValue, AnyValueEnum};
|
||||
|
||||
pub type ExprResult<'a> = Result<AnyValueEnum<'a>, String>;
|
||||
type ExprResultBase<'a, T: AnyValue<'a>> = Result<T, String>;
|
||||
|
||||
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>;
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" {
|
||||
|
|
|
@ -15,10 +15,21 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<String>,
|
||||
pub llvm_value: ExprResult<'a>,
|
||||
pub expr: Expr,
|
||||
}
|
||||
|
||||
impl<'a> Value<'a> {
|
||||
pub fn new(name: Option<String>, expr: Expr, value: ExprResult<'a>) -> Value {
|
||||
Value {
|
||||
llvm_id: name,
|
||||
llvm_value: value,
|
||||
expr: expr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue