mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
Switch back to builtin_defs returning Def
This commit is contained in:
parent
16ceb895c1
commit
07689ca9dc
6 changed files with 182 additions and 112 deletions
|
@ -1,5 +1,7 @@
|
||||||
|
use crate::def::Def;
|
||||||
use crate::expr::{Expr, Recursive};
|
use crate::expr::{Expr, Recursive};
|
||||||
use roc_collections::all::MutMap;
|
use crate::pattern::Pattern;
|
||||||
|
use roc_collections::all::{MutMap, SendMap};
|
||||||
use roc_module::ident::TagName;
|
use roc_module::ident::TagName;
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::operator::CalledVia;
|
use roc_module::operator::CalledVia;
|
||||||
|
@ -24,10 +26,13 @@ use roc_types::subs::{VarStore, Variable};
|
||||||
/// delegates to the compiler-internal List.getUnsafe function to do the actual
|
/// delegates to the compiler-internal List.getUnsafe function to do the actual
|
||||||
/// lookup (if the bounds check passed). That internal function is hardcoded in code gen,
|
/// lookup (if the bounds check passed). That internal function is hardcoded in code gen,
|
||||||
/// which works fine because it doesn't involve any open tag unions.
|
/// which works fine because it doesn't involve any open tag unions.
|
||||||
pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Expr> {
|
pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
|
||||||
mut_map! {
|
mut_map! {
|
||||||
Symbol::BOOL_EQ => bool_eq(var_store),
|
Symbol::BOOL_EQ => bool_eq(var_store),
|
||||||
Symbol::BOOL_NEQ => bool_neq(var_store),
|
Symbol::BOOL_NEQ => bool_neq(var_store),
|
||||||
|
Symbol::BOOL_AND => bool_and(var_store),
|
||||||
|
Symbol::BOOL_OR => bool_or(var_store),
|
||||||
|
Symbol::BOOL_NOT => bool_not(var_store),
|
||||||
Symbol::LIST_LEN => list_len(var_store),
|
Symbol::LIST_LEN => list_len(var_store),
|
||||||
Symbol::LIST_GET => list_get(var_store),
|
Symbol::LIST_GET => list_get(var_store),
|
||||||
Symbol::LIST_FIRST => list_first(var_store),
|
Symbol::LIST_FIRST => list_first(var_store),
|
||||||
|
@ -47,49 +52,109 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Expr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bool.isEq : val, val -> Bool
|
/// Bool.isEq : val, val -> Bool
|
||||||
fn bool_eq(var_store: &mut VarStore) -> Expr {
|
fn bool_eq(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op: LowLevel::Eq,
|
op: LowLevel::Eq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(var_store.fresh(), Var(Symbol::BOOL_EQ_LHS)),
|
(var_store.fresh(), Var(Symbol::BOOL_BINOP_LHS)),
|
||||||
(var_store.fresh(), Var(Symbol::BOOL_EQ_RHS)),
|
(var_store.fresh(), Var(Symbol::BOOL_BINOP_RHS)),
|
||||||
],
|
],
|
||||||
ret_var: var_store.fresh(),
|
ret_var: var_store.fresh(),
|
||||||
};
|
};
|
||||||
|
|
||||||
defn(
|
defn(
|
||||||
Symbol::BOOL_EQ,
|
Symbol::BOOL_EQ,
|
||||||
vec![Symbol::BOOL_EQ_LHS, Symbol::BOOL_EQ_RHS],
|
vec![Symbol::BOOL_BINOP_LHS, Symbol::BOOL_BINOP_RHS],
|
||||||
var_store,
|
var_store,
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bool.isNotEq : val, val -> Bool
|
/// Bool.isNotEq : val, val -> Bool
|
||||||
fn bool_neq(var_store: &mut VarStore) -> Expr {
|
fn bool_neq(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op: LowLevel::NotEq,
|
op: LowLevel::NotEq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(var_store.fresh(), Var(Symbol::BOOL_EQ_LHS)),
|
(var_store.fresh(), Var(Symbol::BOOL_BINOP_LHS)),
|
||||||
(var_store.fresh(), Var(Symbol::BOOL_EQ_RHS)),
|
(var_store.fresh(), Var(Symbol::BOOL_BINOP_RHS)),
|
||||||
],
|
],
|
||||||
ret_var: var_store.fresh(),
|
ret_var: var_store.fresh(),
|
||||||
};
|
};
|
||||||
|
|
||||||
defn(
|
defn(
|
||||||
Symbol::BOOL_NEQ,
|
Symbol::BOOL_NEQ,
|
||||||
vec![Symbol::BOOL_EQ_LHS, Symbol::BOOL_EQ_RHS],
|
vec![Symbol::BOOL_BINOP_LHS, Symbol::BOOL_BINOP_RHS],
|
||||||
|
var_store,
|
||||||
|
body,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bool.or : val, val -> Bool
|
||||||
|
fn bool_or(var_store: &mut VarStore) -> Def {
|
||||||
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
|
let body = RunLowLevel {
|
||||||
|
op: LowLevel::Or,
|
||||||
|
args: vec![
|
||||||
|
(var_store.fresh(), Var(Symbol::BOOL_BINOP_LHS)),
|
||||||
|
(var_store.fresh(), Var(Symbol::BOOL_BINOP_RHS)),
|
||||||
|
],
|
||||||
|
ret_var: var_store.fresh(),
|
||||||
|
};
|
||||||
|
|
||||||
|
defn(
|
||||||
|
Symbol::BOOL_OR,
|
||||||
|
vec![Symbol::BOOL_BINOP_LHS, Symbol::BOOL_BINOP_RHS],
|
||||||
|
var_store,
|
||||||
|
body,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bool.not : Bool -> Bool
|
||||||
|
fn bool_not(var_store: &mut VarStore) -> Def {
|
||||||
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
|
let body = RunLowLevel {
|
||||||
|
op: LowLevel::Not,
|
||||||
|
args: vec![(var_store.fresh(), Var(Symbol::BOOL_BINOP_LHS))],
|
||||||
|
ret_var: var_store.fresh(),
|
||||||
|
};
|
||||||
|
|
||||||
|
defn(
|
||||||
|
Symbol::BOOL_NOT,
|
||||||
|
vec![Symbol::BOOL_BINOP_LHS],
|
||||||
|
var_store,
|
||||||
|
body,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bool.and : val, val -> Bool
|
||||||
|
fn bool_and(var_store: &mut VarStore) -> Def {
|
||||||
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
|
let body = RunLowLevel {
|
||||||
|
op: LowLevel::And,
|
||||||
|
args: vec![
|
||||||
|
(var_store.fresh(), Var(Symbol::BOOL_BINOP_LHS)),
|
||||||
|
(var_store.fresh(), Var(Symbol::BOOL_BINOP_RHS)),
|
||||||
|
],
|
||||||
|
ret_var: var_store.fresh(),
|
||||||
|
};
|
||||||
|
|
||||||
|
defn(
|
||||||
|
Symbol::BOOL_AND,
|
||||||
|
vec![Symbol::BOOL_BINOP_LHS, Symbol::BOOL_BINOP_RHS],
|
||||||
var_store,
|
var_store,
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Float.tan : Float -> Float
|
/// Float.tan : Float -> Float
|
||||||
fn float_tan(var_store: &mut VarStore) -> Expr {
|
fn float_tan(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = call(
|
let body = call(
|
||||||
|
@ -118,7 +183,7 @@ fn float_tan(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Float.isZero : Float -> Bool
|
/// Float.isZero : Float -> Bool
|
||||||
fn float_is_zero(var_store: &mut VarStore) -> Expr {
|
fn float_is_zero(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = call(
|
let body = call(
|
||||||
|
@ -139,7 +204,7 @@ fn float_is_zero(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Float.isNegative : Float -> Bool
|
/// Float.isNegative : Float -> Bool
|
||||||
fn float_is_negative(var_store: &mut VarStore) -> Expr {
|
fn float_is_negative(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = call(
|
let body = call(
|
||||||
|
@ -160,7 +225,7 @@ fn float_is_negative(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Float.isPositive : Float -> Bool
|
/// Float.isPositive : Float -> Bool
|
||||||
fn float_is_positive(var_store: &mut VarStore) -> Expr {
|
fn float_is_positive(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = call(
|
let body = call(
|
||||||
|
@ -181,7 +246,7 @@ fn float_is_positive(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Int.isNegative : Int -> Bool
|
/// Int.isNegative : Int -> Bool
|
||||||
fn int_is_negative(var_store: &mut VarStore) -> Expr {
|
fn int_is_negative(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = call(
|
let body = call(
|
||||||
|
@ -199,7 +264,7 @@ fn int_is_negative(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Int.isPositive : Int -> Bool
|
/// Int.isPositive : Int -> Bool
|
||||||
fn int_is_positive(var_store: &mut VarStore) -> Expr {
|
fn int_is_positive(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = call(
|
let body = call(
|
||||||
|
@ -217,7 +282,7 @@ fn int_is_positive(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Int.isZero : Int -> Bool
|
/// Int.isZero : Int -> Bool
|
||||||
fn int_is_zero(var_store: &mut VarStore) -> Expr {
|
fn int_is_zero(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
|
@ -238,7 +303,7 @@ fn int_is_zero(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Int.isOdd : Int -> Bool
|
/// Int.isOdd : Int -> Bool
|
||||||
fn int_is_odd(var_store: &mut VarStore) -> Expr {
|
fn int_is_odd(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
|
@ -266,7 +331,7 @@ fn int_is_odd(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Int.isEven : Int -> Bool
|
/// Int.isEven : Int -> Bool
|
||||||
fn int_is_even(var_store: &mut VarStore) -> Expr {
|
fn int_is_even(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
|
@ -287,7 +352,7 @@ fn int_is_even(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List.len : List * -> Int
|
/// List.len : List * -> Int
|
||||||
fn list_len(var_store: &mut VarStore) -> Expr {
|
fn list_len(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
// Polymorphic wrapper around LowLevel::ListLen
|
// Polymorphic wrapper around LowLevel::ListLen
|
||||||
|
@ -308,7 +373,7 @@ fn list_len(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List.get : List elem, Int -> Result elem [ OutOfBounds ]*
|
/// List.get : List elem, Int -> Result elem [ OutOfBounds ]*
|
||||||
fn list_get(var_store: &mut VarStore) -> Expr {
|
fn list_get(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
// Perform a bounds check. If it passes, delegate to List.#getUnsafe
|
// Perform a bounds check. If it passes, delegate to List.#getUnsafe
|
||||||
|
@ -380,7 +445,7 @@ fn list_get(var_store: &mut VarStore) -> Expr {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/// Int.rem : Int, Int -> Int
|
/// Int.rem : Int, Int -> Int
|
||||||
fn int_rem(var_store: &mut VarStore) -> Expr {
|
fn int_rem(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
|
@ -432,7 +497,7 @@ fn int_rem(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Int.abs : Int -> Int
|
/// Int.abs : Int -> Int
|
||||||
fn int_abs(var_store: &mut VarStore) -> Expr {
|
fn int_abs(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
|
@ -466,7 +531,7 @@ fn int_abs(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Int.div : Int, Int -> Result Int [ DivByZero ]*
|
/// Int.div : Int, Int -> Result Int [ DivByZero ]*
|
||||||
fn int_div(var_store: &mut VarStore) -> Expr {
|
fn int_div(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
let body = If {
|
let body = If {
|
||||||
|
@ -527,7 +592,7 @@ fn int_div(var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List.first : List elem -> Result elem [ ListWasEmpty ]*
|
/// List.first : List elem -> Result elem [ ListWasEmpty ]*
|
||||||
fn list_first(var_store: &mut VarStore) -> Expr {
|
fn list_first(var_store: &mut VarStore) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
|
|
||||||
// Perform a bounds check. If it passes, delegate to List.getUnsafe.
|
// Perform a bounds check. If it passes, delegate to List.getUnsafe.
|
||||||
|
@ -621,7 +686,7 @@ fn call(symbol: Symbol, args: Vec<Expr>, var_store: &mut VarStore) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn defn(fn_name: Symbol, args: Vec<Symbol>, var_store: &mut VarStore, body: Expr) -> Expr {
|
fn defn(fn_name: Symbol, args: Vec<Symbol>, var_store: &mut VarStore, body: Expr) -> Def {
|
||||||
use crate::expr::Expr::*;
|
use crate::expr::Expr::*;
|
||||||
use crate::pattern::Pattern::*;
|
use crate::pattern::Pattern::*;
|
||||||
|
|
||||||
|
@ -630,11 +695,27 @@ fn defn(fn_name: Symbol, args: Vec<Symbol>, var_store: &mut VarStore, body: Expr
|
||||||
.map(|symbol| (var_store.fresh(), no_region(Identifier(symbol))))
|
.map(|symbol| (var_store.fresh(), no_region(Identifier(symbol))))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Closure(
|
let expr = Closure(
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
fn_name,
|
fn_name,
|
||||||
Recursive::NotRecursive,
|
Recursive::NotRecursive,
|
||||||
closure_args,
|
closure_args,
|
||||||
Box::new((no_region(body), var_store.fresh())),
|
Box::new((no_region(body), var_store.fresh())),
|
||||||
)
|
);
|
||||||
|
|
||||||
|
let annotation = None; // TODO
|
||||||
|
|
||||||
|
Def {
|
||||||
|
loc_pattern: Located {
|
||||||
|
region: Region::zero(),
|
||||||
|
value: Pattern::Identifier(fn_name),
|
||||||
|
},
|
||||||
|
loc_expr: Located {
|
||||||
|
region: Region::zero(),
|
||||||
|
value: expr,
|
||||||
|
},
|
||||||
|
expr_var: var_store.fresh(),
|
||||||
|
pattern_vars: SendMap::default(),
|
||||||
|
annotation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,49 +287,7 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
build_expr(env, layout_ids, &scope, parent, ret)
|
build_expr(env, layout_ids, &scope, parent, ret)
|
||||||
}
|
}
|
||||||
CallByName { name, layout, args } => match *name {
|
CallByName { name, layout, args } => {
|
||||||
Symbol::BOOL_OR => {
|
|
||||||
// The (||) operator
|
|
||||||
debug_assert!(args.len() == 2);
|
|
||||||
|
|
||||||
let comparison =
|
|
||||||
build_expr(env, layout_ids, scope, parent, &args[0].0).into_int_value();
|
|
||||||
let build_then = || env.context.bool_type().const_int(true as u64, false).into();
|
|
||||||
let build_else = || build_expr(env, layout_ids, scope, parent, &args[1].0);
|
|
||||||
|
|
||||||
let ret_type = env.context.bool_type().into();
|
|
||||||
|
|
||||||
build_basic_phi2(env, parent, comparison, build_then, build_else, ret_type)
|
|
||||||
}
|
|
||||||
Symbol::BOOL_AND => {
|
|
||||||
// The (&&) operator
|
|
||||||
debug_assert!(args.len() == 2);
|
|
||||||
|
|
||||||
let comparison =
|
|
||||||
build_expr(env, layout_ids, scope, parent, &args[0].0).into_int_value();
|
|
||||||
let build_then = || build_expr(env, layout_ids, scope, parent, &args[1].0);
|
|
||||||
let build_else = || {
|
|
||||||
env.context
|
|
||||||
.bool_type()
|
|
||||||
.const_int(false as u64, false)
|
|
||||||
.into()
|
|
||||||
};
|
|
||||||
|
|
||||||
let ret_type = env.context.bool_type().into();
|
|
||||||
|
|
||||||
build_basic_phi2(env, parent, comparison, build_then, build_else, ret_type)
|
|
||||||
}
|
|
||||||
Symbol::BOOL_NOT => {
|
|
||||||
// The (!) operator
|
|
||||||
debug_assert!(args.len() == 1);
|
|
||||||
|
|
||||||
let arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
|
||||||
|
|
||||||
let int_val = env.builder.build_not(arg.into_int_value(), "bool_not");
|
|
||||||
|
|
||||||
BasicValueEnum::IntValue(int_val)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let mut arg_tuples: Vec<(BasicValueEnum, &'a Layout<'a>)> =
|
let mut arg_tuples: Vec<(BasicValueEnum, &'a Layout<'a>)> =
|
||||||
Vec::with_capacity_in(args.len(), env.arena);
|
Vec::with_capacity_in(args.len(), env.arena);
|
||||||
|
|
||||||
|
@ -346,7 +304,6 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
arg_tuples.into_bump_slice(),
|
arg_tuples.into_bump_slice(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
FunctionPointer(symbol, layout) => {
|
FunctionPointer(symbol, layout) => {
|
||||||
let fn_name = layout_ids
|
let fn_name = layout_ids
|
||||||
.get(*symbol, layout)
|
.get(*symbol, layout)
|
||||||
|
@ -1425,7 +1382,13 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
let fn_val = env
|
let fn_val = env
|
||||||
.module
|
.module
|
||||||
.get_function(fn_name.as_str())
|
.get_function(fn_name.as_str())
|
||||||
.unwrap_or_else(|| panic!("Unrecognized function: {:?}", symbol));
|
.unwrap_or_else(|| {
|
||||||
|
if symbol.is_builtin() {
|
||||||
|
panic!("Unrecognized builtin function: {:?}", symbol)
|
||||||
|
} else {
|
||||||
|
panic!("Unrecognized non-builtin function: {:?}", symbol)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let mut arg_vals: Vec<BasicValueEnum> = Vec::with_capacity_in(args.len(), env.arena);
|
let mut arg_vals: Vec<BasicValueEnum> = Vec::with_capacity_in(args.len(), env.arena);
|
||||||
|
|
||||||
|
@ -1705,5 +1668,42 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
build_neq(env, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
build_neq(env, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||||
}
|
}
|
||||||
|
And => {
|
||||||
|
// The (&&) operator
|
||||||
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
||||||
|
let lhs_arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
||||||
|
let rhs_arg = build_expr(env, layout_ids, scope, parent, &args[1].0);
|
||||||
|
let bool_val = env.builder.build_and(
|
||||||
|
lhs_arg.into_int_value(),
|
||||||
|
rhs_arg.into_int_value(),
|
||||||
|
"bool_and",
|
||||||
|
);
|
||||||
|
|
||||||
|
BasicValueEnum::IntValue(bool_val)
|
||||||
|
}
|
||||||
|
Or => {
|
||||||
|
// The (||) operator
|
||||||
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
||||||
|
let lhs_arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
||||||
|
let rhs_arg = build_expr(env, layout_ids, scope, parent, &args[1].0);
|
||||||
|
let bool_val = env.builder.build_or(
|
||||||
|
lhs_arg.into_int_value(),
|
||||||
|
rhs_arg.into_int_value(),
|
||||||
|
"bool_or",
|
||||||
|
);
|
||||||
|
|
||||||
|
BasicValueEnum::IntValue(bool_val)
|
||||||
|
}
|
||||||
|
Not => {
|
||||||
|
// The (!) operator
|
||||||
|
debug_assert_eq!(args.len(), 1);
|
||||||
|
|
||||||
|
let arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
||||||
|
let bool_val = env.builder.build_not(arg.into_int_value(), "bool_not");
|
||||||
|
|
||||||
|
BasicValueEnum::IntValue(bool_val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ mod helpers;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod gen_tags {
|
mod gen_tags {
|
||||||
use crate::helpers::{can_expr, infer_expr, uniq_expr, with_larger_debug_stack, CanExprOut};
|
use crate::helpers::{can_expr, infer_expr, uniq_expr, CanExprOut};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use inkwell::execution_engine::JitFunction;
|
use inkwell::execution_engine::JitFunction;
|
||||||
|
@ -213,7 +213,6 @@ mod gen_tags {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn even_odd() {
|
fn even_odd() {
|
||||||
with_larger_debug_stack(|| {
|
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
|
@ -235,7 +234,6 @@ mod gen_tags {
|
||||||
true,
|
true,
|
||||||
bool
|
bool
|
||||||
);
|
);
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -247,23 +247,11 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
|
||||||
// since we aren't using modules here.
|
// since we aren't using modules here.
|
||||||
let builtin_defs = roc_can::builtins::builtin_defs(&mut var_store);
|
let builtin_defs = roc_can::builtins::builtin_defs(&mut var_store);
|
||||||
|
|
||||||
for (symbol, expr) in builtin_defs {
|
for (symbol, def) in builtin_defs {
|
||||||
if output.references.lookups.contains(&symbol) || output.references.calls.contains(&symbol)
|
if output.references.lookups.contains(&symbol) || output.references.calls.contains(&symbol)
|
||||||
{
|
{
|
||||||
with_builtins = Expr::LetNonRec(
|
with_builtins = Expr::LetNonRec(
|
||||||
Box::new(Def {
|
Box::new(def),
|
||||||
loc_pattern: Located {
|
|
||||||
region: Region::zero(),
|
|
||||||
value: Pattern::Identifier(symbol),
|
|
||||||
},
|
|
||||||
loc_expr: Located {
|
|
||||||
region: Region::zero(),
|
|
||||||
value: expr,
|
|
||||||
},
|
|
||||||
expr_var: var_store.fresh(),
|
|
||||||
pattern_vars: SendMap::default(),
|
|
||||||
annotation: None,
|
|
||||||
}),
|
|
||||||
Box::new(Located {
|
Box::new(Located {
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
value: with_builtins,
|
value: with_builtins,
|
||||||
|
|
|
@ -7,4 +7,7 @@ pub enum LowLevel {
|
||||||
ListLen,
|
ListLen,
|
||||||
Eq,
|
Eq,
|
||||||
NotEq,
|
NotEq,
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
Not,
|
||||||
}
|
}
|
||||||
|
|
|
@ -661,8 +661,8 @@ define_builtins! {
|
||||||
4 BOOL_XOR: "xor"
|
4 BOOL_XOR: "xor"
|
||||||
5 BOOL_EQ: "isEq"
|
5 BOOL_EQ: "isEq"
|
||||||
6 BOOL_NEQ: "isNotEq"
|
6 BOOL_NEQ: "isNotEq"
|
||||||
7 BOOL_EQ_LHS: "eq#lhs"
|
7 BOOL_BINOP_LHS: "bool#lhs"
|
||||||
8 BOOL_EQ_RHS: "eq#rhs"
|
8 BOOL_BINOP_RHS: "bool#rhs"
|
||||||
}
|
}
|
||||||
5 STR: "Str" => {
|
5 STR: "Str" => {
|
||||||
0 STR_STR: "Str" imported // the Str.Str type alias
|
0 STR_STR: "Str" imported // the Str.Str type alias
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue