From 7ede4f15b6728ba9340eea580c5daa5791cdb438 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Wed, 1 Dec 2021 02:52:00 +0800 Subject: [PATCH 1/2] nac3core: move builtin definitions to another file --- nac3core/src/toplevel/builtins.rs | 407 ++++++++++++++++++++++++++++++ nac3core/src/toplevel/composer.rs | 401 +---------------------------- nac3core/src/toplevel/mod.rs | 1 + 3 files changed, 409 insertions(+), 400 deletions(-) create mode 100644 nac3core/src/toplevel/builtins.rs diff --git a/nac3core/src/toplevel/builtins.rs b/nac3core/src/toplevel/builtins.rs new file mode 100644 index 000000000..97d9f8ff4 --- /dev/null +++ b/nac3core/src/toplevel/builtins.rs @@ -0,0 +1,407 @@ +use std::cell::RefCell; + +use inkwell::{IntPredicate, FloatPredicate}; + +use crate::symbol_resolver::SymbolValue; + +use super::*; + +pub fn get_built_ins(primitives: &mut (PrimitiveStore, Unifier)) -> Vec<(Arc>, Option)> { + let int32 = primitives.0.int32; + let int64 = primitives.0.int64; + let float = primitives.0.float; + let boolean = primitives.0.bool; + let range = primitives.0.range; + let string = primitives.0.str; + let num_ty = primitives.1.get_fresh_var_with_range(&[int32, int64, float, boolean]); + let var_map: HashMap<_, _> = vec![(num_ty.1, num_ty.0)].into_iter().collect(); + + let top_level_def_list = vec![ + Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( + 0, + None, + "int32".into(), + None, + ))), + Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( + 1, + None, + "int64".into(), + None, + ))), + Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( + 2, + None, + "float".into(), + None, + ))), + Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def(3, None, "bool".into(), None))), + Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def(4, None, "none".into(), None))), + Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def( + 5, + None, + "range".into(), + None, + ))), + Arc::new(RwLock::new(TopLevelComposer::make_top_level_class_def(6, None, "str".into(), None))), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "int32".into(), + simple_name: "int32".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], + ret: int32, + vars: var_map.clone(), + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new( + |ctx, _, fun, args| { + let int32 = ctx.primitives.int32; + let int64 = ctx.primitives.int64; + let float = ctx.primitives.float; + let boolean = ctx.primitives.bool; + let arg_ty = fun.0.args[0].ty; + let arg = args[0].1; + if ctx.unifier.unioned(arg_ty, boolean) { + Some( + ctx.builder + .build_int_s_extend( + arg.into_int_value(), + ctx.ctx.i32_type(), + "sext", + ) + .into(), + ) + } else if ctx.unifier.unioned(arg_ty, int32) { + Some(arg) + } else if ctx.unifier.unioned(arg_ty, int64) { + Some( + ctx.builder + .build_int_truncate( + arg.into_int_value(), + ctx.ctx.i32_type(), + "trunc", + ) + .into(), + ) + } else if ctx.unifier.unioned(arg_ty, float) { + let val = ctx + .builder + .build_float_to_signed_int( + arg.into_float_value(), + ctx.ctx.i32_type(), + "fptosi", + ) + .into(); + Some(val) + } else { + unreachable!() + } + }, + )))), + })), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "int64".into(), + simple_name: "int64".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], + ret: int64, + vars: var_map.clone(), + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new( + |ctx, _, fun, args| { + let int32 = ctx.primitives.int32; + let int64 = ctx.primitives.int64; + let float = ctx.primitives.float; + let boolean = ctx.primitives.bool; + let arg_ty = fun.0.args[0].ty; + let arg = args[0].1; + if ctx.unifier.unioned(arg_ty, boolean) + || ctx.unifier.unioned(arg_ty, int32) + { + Some( + ctx.builder + .build_int_s_extend( + arg.into_int_value(), + ctx.ctx.i64_type(), + "sext", + ) + .into(), + ) + } else if ctx.unifier.unioned(arg_ty, int64) { + Some(arg) + } else if ctx.unifier.unioned(arg_ty, float) { + let val = ctx + .builder + .build_float_to_signed_int( + arg.into_float_value(), + ctx.ctx.i64_type(), + "fptosi", + ) + .into(); + Some(val) + } else { + unreachable!() + } + }, + )))), + })), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "float".into(), + simple_name: "float".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], + ret: float, + vars: var_map.clone(), + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new( + |ctx, _, fun, args| { + let int32 = ctx.primitives.int32; + let int64 = ctx.primitives.int64; + let boolean = ctx.primitives.bool; + let float = ctx.primitives.float; + let arg_ty = fun.0.args[0].ty; + let arg = args[0].1; + if ctx.unifier.unioned(arg_ty, boolean) + || ctx.unifier.unioned(arg_ty, int32) + || ctx.unifier.unioned(arg_ty, int64) + { + let arg = args[0].1.into_int_value(); + let val = ctx + .builder + .build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp") + .into(); + Some(val) + } else if ctx.unifier.unioned(arg_ty, float) { + Some(arg) + } else { + unreachable!() + } + }, + )))), + })), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "round".into(), + simple_name: "round".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![FuncArg { name: "_".into(), ty: float, default_value: None }], + ret: int32, + vars: Default::default(), + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| { + let arg = args[0].1; + let round_intrinsic = + ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { + let float = ctx.ctx.f64_type(); + let fn_type = float.fn_type(&[float.into()], false); + ctx.module.add_function("llvm.round.f64", fn_type, None) + }); + let val = ctx + .builder + .build_call(round_intrinsic, &[arg], "round") + .try_as_basic_value() + .left() + .unwrap(); + Some( + ctx.builder + .build_float_to_signed_int( + val.into_float_value(), + ctx.ctx.i32_type(), + "fptosi", + ) + .into(), + ) + })))), + })), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "round64".into(), + simple_name: "round64".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![FuncArg { name: "_".into(), ty: float, default_value: None }], + ret: int64, + vars: Default::default(), + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| { + let arg = args[0].1; + let round_intrinsic = + ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { + let float = ctx.ctx.f64_type(); + let fn_type = float.fn_type(&[float.into()], false); + ctx.module.add_function("llvm.round.f64", fn_type, None) + }); + let val = ctx + .builder + .build_call(round_intrinsic, &[arg], "round") + .try_as_basic_value() + .left() + .unwrap(); + Some( + ctx.builder + .build_float_to_signed_int( + val.into_float_value(), + ctx.ctx.i64_type(), + "fptosi", + ) + .into(), + ) + })))), + })), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "range".into(), + simple_name: "range".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![ + FuncArg { name: "start".into(), ty: int32, default_value: None }, + FuncArg { + name: "stop".into(), + ty: int32, + // placeholder + default_value: Some(SymbolValue::I32(0)), + }, + FuncArg { + name: "step".into(), + ty: int32, + default_value: Some(SymbolValue::I32(1)), + }, + ], + ret: range, + vars: Default::default(), + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| { + let mut start = None; + let mut stop = None; + let mut step = None; + let int32 = ctx.ctx.i32_type(); + let zero = int32.const_zero(); + for (i, arg) in args.iter().enumerate() { + if arg.0 == Some("start".into()) { + start = Some(arg.1); + } else if arg.0 == Some("stop".into()) { + stop = Some(arg.1); + } else if arg.0 == Some("step".into()) { + step = Some(arg.1); + } else if i == 0 { + start = Some(arg.1); + } else if i == 1 { + stop = Some(arg.1); + } else if i == 2 { + step = Some(arg.1); + } + } + // TODO: error when step == 0 + let step = step.unwrap_or_else(|| int32.const_int(1, false).into()); + let stop = stop.unwrap_or_else(|| { + let v = start.unwrap(); + start = None; + v + }); + let start = start.unwrap_or_else(|| int32.const_zero().into()); + let ty = int32.array_type(3); + let ptr = ctx.builder.build_alloca(ty, "range"); + unsafe { + let a = ctx.builder.build_in_bounds_gep(ptr, &[zero, zero], "start"); + let b = ctx.builder.build_in_bounds_gep( + ptr, + &[zero, int32.const_int(1, false)], + "end", + ); + let c = ctx.builder.build_in_bounds_gep( + ptr, + &[zero, int32.const_int(2, false)], + "step", + ); + ctx.builder.build_store(a, start); + ctx.builder.build_store(b, stop); + ctx.builder.build_store(c, step); + } + Some(ptr.into()) + })))), + })), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "str".into(), + simple_name: "str".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![FuncArg { name: "_".into(), ty: string, default_value: None }], + ret: string, + vars: Default::default(), + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new(|_, _, _, args| { + Some(args[0].1) + })))), + })), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "bool".into(), + simple_name: "bool".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], + ret: primitives.0.bool, + vars: var_map, + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new( + |ctx, _, fun, args| { + let int32 = ctx.primitives.int32; + let int64 = ctx.primitives.int64; + let float = ctx.primitives.float; + let boolean = ctx.primitives.bool; + let arg_ty = fun.0.args[0].ty; + let arg = args[0].1; + if ctx.unifier.unioned(arg_ty, boolean) { + Some(arg) + } else if ctx.unifier.unioned(arg_ty, int32) || ctx.unifier.unioned(arg_ty, int64) { + Some(ctx.builder.build_int_compare( + IntPredicate::NE, + ctx.ctx.i64_type().const_zero(), + arg.into_int_value(), + "bool", + ).into()) + } else if ctx.unifier.unioned(arg_ty, float) { + let val = ctx.builder. + build_float_compare( + // UEQ as bool(nan) is True + FloatPredicate::UEQ, + arg.into_float_value(), + ctx.ctx.f64_type().const_zero(), + "bool" + ).into(); + Some(val) + } else { + unreachable!() + } + }, + )))), + })), + ]; + let ast_list: Vec>> = + (0..top_level_def_list.len()).map(|_| None).collect(); + izip!(top_level_def_list, ast_list).collect_vec() +} \ No newline at end of file diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index a059362a6..4eabb983e 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -42,406 +42,7 @@ impl TopLevelComposer { builtins: Vec<(StrRef, FunSignature, Arc)>, ) -> (Self, HashMap, HashMap) { let mut primitives = Self::make_primitives(); - - let int32 = primitives.0.int32; - let int64 = primitives.0.int64; - let float = primitives.0.float; - let boolean = primitives.0.bool; - let range = primitives.0.range; - let string = primitives.0.str; - let num_ty = primitives.1.get_fresh_var_with_range(&[int32, int64, float, boolean]); - let var_map: HashMap<_, _> = vec![(num_ty.1, num_ty.0)].into_iter().collect(); - - let mut definition_ast_list = { - let top_level_def_list = vec![ - Arc::new(RwLock::new(Self::make_top_level_class_def( - 0, - None, - "int32".into(), - None, - ))), - Arc::new(RwLock::new(Self::make_top_level_class_def( - 1, - None, - "int64".into(), - None, - ))), - Arc::new(RwLock::new(Self::make_top_level_class_def( - 2, - None, - "float".into(), - None, - ))), - Arc::new(RwLock::new(Self::make_top_level_class_def(3, None, "bool".into(), None))), - Arc::new(RwLock::new(Self::make_top_level_class_def(4, None, "none".into(), None))), - Arc::new(RwLock::new(Self::make_top_level_class_def( - 5, - None, - "range".into(), - None, - ))), - Arc::new(RwLock::new(Self::make_top_level_class_def(6, None, "str".into(), None))), - Arc::new(RwLock::new(TopLevelDef::Function { - name: "int32".into(), - simple_name: "int32".into(), - signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { - args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], - ret: int32, - vars: var_map.clone(), - }))), - var_id: Default::default(), - instance_to_symbol: Default::default(), - instance_to_stmt: Default::default(), - resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new( - |ctx, _, fun, args| { - let int32 = ctx.primitives.int32; - let int64 = ctx.primitives.int64; - let float = ctx.primitives.float; - let boolean = ctx.primitives.bool; - let arg_ty = fun.0.args[0].ty; - let arg = args[0].1; - if ctx.unifier.unioned(arg_ty, boolean) { - Some( - ctx.builder - .build_int_s_extend( - arg.into_int_value(), - ctx.ctx.i32_type(), - "sext", - ) - .into(), - ) - } else if ctx.unifier.unioned(arg_ty, int32) { - Some(arg) - } else if ctx.unifier.unioned(arg_ty, int64) { - Some( - ctx.builder - .build_int_truncate( - arg.into_int_value(), - ctx.ctx.i32_type(), - "trunc", - ) - .into(), - ) - } else if ctx.unifier.unioned(arg_ty, float) { - let val = ctx - .builder - .build_float_to_signed_int( - arg.into_float_value(), - ctx.ctx.i32_type(), - "fptosi", - ) - .into(); - Some(val) - } else { - unreachable!() - } - }, - )))), - })), - Arc::new(RwLock::new(TopLevelDef::Function { - name: "int64".into(), - simple_name: "int64".into(), - signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { - args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], - ret: int64, - vars: var_map.clone(), - }))), - var_id: Default::default(), - instance_to_symbol: Default::default(), - instance_to_stmt: Default::default(), - resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new( - |ctx, _, fun, args| { - let int32 = ctx.primitives.int32; - let int64 = ctx.primitives.int64; - let float = ctx.primitives.float; - let boolean = ctx.primitives.bool; - let arg_ty = fun.0.args[0].ty; - let arg = args[0].1; - if ctx.unifier.unioned(arg_ty, boolean) - || ctx.unifier.unioned(arg_ty, int32) - { - Some( - ctx.builder - .build_int_s_extend( - arg.into_int_value(), - ctx.ctx.i64_type(), - "sext", - ) - .into(), - ) - } else if ctx.unifier.unioned(arg_ty, int64) { - Some(arg) - } else if ctx.unifier.unioned(arg_ty, float) { - let val = ctx - .builder - .build_float_to_signed_int( - arg.into_float_value(), - ctx.ctx.i64_type(), - "fptosi", - ) - .into(); - Some(val) - } else { - unreachable!() - } - }, - )))), - })), - Arc::new(RwLock::new(TopLevelDef::Function { - name: "float".into(), - simple_name: "float".into(), - signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { - args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], - ret: float, - vars: var_map.clone(), - }))), - var_id: Default::default(), - instance_to_symbol: Default::default(), - instance_to_stmt: Default::default(), - resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new( - |ctx, _, fun, args| { - let int32 = ctx.primitives.int32; - let int64 = ctx.primitives.int64; - let boolean = ctx.primitives.bool; - let float = ctx.primitives.float; - let arg_ty = fun.0.args[0].ty; - let arg = args[0].1; - if ctx.unifier.unioned(arg_ty, boolean) - || ctx.unifier.unioned(arg_ty, int32) - || ctx.unifier.unioned(arg_ty, int64) - { - let arg = args[0].1.into_int_value(); - let val = ctx - .builder - .build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp") - .into(); - Some(val) - } else if ctx.unifier.unioned(arg_ty, float) { - Some(arg) - } else { - unreachable!() - } - }, - )))), - })), - Arc::new(RwLock::new(TopLevelDef::Function { - name: "round".into(), - simple_name: "round".into(), - signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { - args: vec![FuncArg { name: "_".into(), ty: float, default_value: None }], - ret: int32, - vars: Default::default(), - }))), - var_id: Default::default(), - instance_to_symbol: Default::default(), - instance_to_stmt: Default::default(), - resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| { - let arg = args[0].1; - let round_intrinsic = - ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { - let float = ctx.ctx.f64_type(); - let fn_type = float.fn_type(&[float.into()], false); - ctx.module.add_function("llvm.round.f64", fn_type, None) - }); - let val = ctx - .builder - .build_call(round_intrinsic, &[arg], "round") - .try_as_basic_value() - .left() - .unwrap(); - Some( - ctx.builder - .build_float_to_signed_int( - val.into_float_value(), - ctx.ctx.i32_type(), - "fptosi", - ) - .into(), - ) - })))), - })), - Arc::new(RwLock::new(TopLevelDef::Function { - name: "round64".into(), - simple_name: "round64".into(), - signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { - args: vec![FuncArg { name: "_".into(), ty: float, default_value: None }], - ret: int64, - vars: Default::default(), - }))), - var_id: Default::default(), - instance_to_symbol: Default::default(), - instance_to_stmt: Default::default(), - resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| { - let arg = args[0].1; - let round_intrinsic = - ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { - let float = ctx.ctx.f64_type(); - let fn_type = float.fn_type(&[float.into()], false); - ctx.module.add_function("llvm.round.f64", fn_type, None) - }); - let val = ctx - .builder - .build_call(round_intrinsic, &[arg], "round") - .try_as_basic_value() - .left() - .unwrap(); - Some( - ctx.builder - .build_float_to_signed_int( - val.into_float_value(), - ctx.ctx.i64_type(), - "fptosi", - ) - .into(), - ) - })))), - })), - Arc::new(RwLock::new(TopLevelDef::Function { - name: "range".into(), - simple_name: "range".into(), - signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { - args: vec![ - FuncArg { name: "start".into(), ty: int32, default_value: None }, - FuncArg { - name: "stop".into(), - ty: int32, - // placeholder - default_value: Some(SymbolValue::I32(0)), - }, - FuncArg { - name: "step".into(), - ty: int32, - default_value: Some(SymbolValue::I32(1)), - }, - ], - ret: range, - vars: Default::default(), - }))), - var_id: Default::default(), - instance_to_symbol: Default::default(), - instance_to_stmt: Default::default(), - resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| { - let mut start = None; - let mut stop = None; - let mut step = None; - let int32 = ctx.ctx.i32_type(); - let zero = int32.const_zero(); - for (i, arg) in args.iter().enumerate() { - if arg.0 == Some("start".into()) { - start = Some(arg.1); - } else if arg.0 == Some("stop".into()) { - stop = Some(arg.1); - } else if arg.0 == Some("step".into()) { - step = Some(arg.1); - } else if i == 0 { - start = Some(arg.1); - } else if i == 1 { - stop = Some(arg.1); - } else if i == 2 { - step = Some(arg.1); - } - } - // TODO: error when step == 0 - let step = step.unwrap_or_else(|| int32.const_int(1, false).into()); - let stop = stop.unwrap_or_else(|| { - let v = start.unwrap(); - start = None; - v - }); - let start = start.unwrap_or_else(|| int32.const_zero().into()); - let ty = int32.array_type(3); - let ptr = ctx.builder.build_alloca(ty, "range"); - unsafe { - let a = ctx.builder.build_in_bounds_gep(ptr, &[zero, zero], "start"); - let b = ctx.builder.build_in_bounds_gep( - ptr, - &[zero, int32.const_int(1, false)], - "end", - ); - let c = ctx.builder.build_in_bounds_gep( - ptr, - &[zero, int32.const_int(2, false)], - "step", - ); - ctx.builder.build_store(a, start); - ctx.builder.build_store(b, stop); - ctx.builder.build_store(c, step); - } - Some(ptr.into()) - })))), - })), - Arc::new(RwLock::new(TopLevelDef::Function { - name: "str".into(), - simple_name: "str".into(), - signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { - args: vec![FuncArg { name: "_".into(), ty: string, default_value: None }], - ret: string, - vars: Default::default(), - }))), - var_id: Default::default(), - instance_to_symbol: Default::default(), - instance_to_stmt: Default::default(), - resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new(|_, _, _, args| { - Some(args[0].1) - })))), - })), - Arc::new(RwLock::new(TopLevelDef::Function { - name: "bool".into(), - simple_name: "bool".into(), - signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { - args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], - ret: primitives.0.bool, - vars: var_map, - }))), - var_id: Default::default(), - instance_to_symbol: Default::default(), - instance_to_stmt: Default::default(), - resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new( - |ctx, _, fun, args| { - let int32 = ctx.primitives.int32; - let int64 = ctx.primitives.int64; - let float = ctx.primitives.float; - let boolean = ctx.primitives.bool; - let arg_ty = fun.0.args[0].ty; - let arg = args[0].1; - if ctx.unifier.unioned(arg_ty, boolean) { - Some(arg) - } else if ctx.unifier.unioned(arg_ty, int32) || ctx.unifier.unioned(arg_ty, int64) { - Some(ctx.builder.build_int_compare( - IntPredicate::NE, - ctx.ctx.i64_type().const_zero(), - arg.into_int_value(), - "bool", - ).into()) - } else if ctx.unifier.unioned(arg_ty, float) { - let val = ctx.builder. - build_float_compare( - // UEQ as bool(nan) is True - FloatPredicate::UEQ, - arg.into_float_value(), - ctx.ctx.f64_type().const_zero(), - "bool" - ).into(); - Some(val) - } else { - unreachable!() - } - }, - )))), - })), - ]; - let ast_list: Vec>> = - (0..top_level_def_list.len()).map(|_| None).collect(); - izip!(top_level_def_list, ast_list).collect_vec() - }; + let mut definition_ast_list = builtins::get_built_ins(&mut primitives); let primitives_ty = primitives.0; let mut unifier = primitives.1; let mut keyword_list: HashSet = HashSet::from_iter(vec![ diff --git a/nac3core/src/toplevel/mod.rs b/nac3core/src/toplevel/mod.rs index f6fc15b06..55e3fe924 100644 --- a/nac3core/src/toplevel/mod.rs +++ b/nac3core/src/toplevel/mod.rs @@ -25,6 +25,7 @@ pub struct DefinitionId(pub usize); pub mod composer; pub mod helper; mod type_annotation; +pub mod builtins; use composer::*; use type_annotation::*; #[cfg(test)] From fa2fe8ed5d98f7ac3bd6794030a3af6b5da4e7fa Mon Sep 17 00:00:00 2001 From: ychenfo Date: Wed, 1 Dec 2021 03:23:58 +0800 Subject: [PATCH 2/2] nac3core: add ceil and floor --- nac3core/src/toplevel/builtins.rs | 176 +++++++++++++++++++++++++++++- nac3core/src/toplevel/composer.rs | 6 +- 2 files changed, 173 insertions(+), 9 deletions(-) diff --git a/nac3core/src/toplevel/builtins.rs b/nac3core/src/toplevel/builtins.rs index 97d9f8ff4..3d2f4b717 100644 --- a/nac3core/src/toplevel/builtins.rs +++ b/nac3core/src/toplevel/builtins.rs @@ -1,12 +1,14 @@ use std::cell::RefCell; - use inkwell::{IntPredicate, FloatPredicate}; - use crate::symbol_resolver::SymbolValue; - use super::*; -pub fn get_built_ins(primitives: &mut (PrimitiveStore, Unifier)) -> Vec<(Arc>, Option)> { +type BuiltinInfo = ( + Vec<(Arc>, Option)>, + &'static [&'static str] +); + +pub fn get_built_ins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let int32 = primitives.0.int32; let int64 = primitives.0.int64; let float = primitives.0.float; @@ -400,8 +402,172 @@ pub fn get_built_ins(primitives: &mut (PrimitiveStore, Unifier)) -> Vec<(Arc>> = (0..top_level_def_list.len()).map(|_| None).collect(); - izip!(top_level_def_list, ast_list).collect_vec() + ( + izip!(top_level_def_list, ast_list).collect_vec(), + &[ + "int32", + "int64", + "float", + "round", + "round64", + "range", + "str", + "bool", + "floor", + "floor64", + "ceil", + "ceil64" + ] + ) } \ No newline at end of file diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 4eabb983e..051af13f8 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -42,7 +42,7 @@ impl TopLevelComposer { builtins: Vec<(StrRef, FunSignature, Arc)>, ) -> (Self, HashMap, HashMap) { let mut primitives = Self::make_primitives(); - let mut definition_ast_list = builtins::get_built_ins(&mut primitives); + let (mut definition_ast_list, builtin_name_list) = builtins::get_built_ins(&mut primitives); let primitives_ty = primitives.0; let mut unifier = primitives.1; let mut keyword_list: HashSet = HashSet::from_iter(vec![ @@ -68,9 +68,7 @@ impl TopLevelComposer { let mut built_in_id: HashMap = Default::default(); let mut built_in_ty: HashMap = Default::default(); - for (id, name) in - ["int32", "int64", "float", "round", "round64", "range", "str", "bool"].iter().rev().enumerate() - { + for (id, name) in builtin_name_list.iter().rev().enumerate() { let name = (**name).into(); let id = definition_ast_list.len() - id - 1; let def = definition_ast_list[id].0.read();