forked from M-Labs/nac3
core: refactor to use RangeObject / Range
This commit is contained in:
parent
122f55e615
commit
2b29f7b0f5
|
@ -1,10 +1,10 @@
|
|||
use nac3core::{
|
||||
codegen::{
|
||||
classes::{ListValue, RangeValue, UntypedArrayLikeAccessor},
|
||||
expr::{destructure_range, gen_call},
|
||||
classes::{ListValue, UntypedArrayLikeAccessor},
|
||||
expr::gen_call,
|
||||
llvm_intrinsics::{call_int_smax, call_stackrestore, call_stacksave},
|
||||
model::*,
|
||||
object::{any::AnyObject, ndarray::NDArrayObject},
|
||||
object::{any::AnyObject, ndarray::NDArrayObject, range::RangeObject},
|
||||
stmt::{gen_block, gen_for_callback_incrementing, gen_if_callback, gen_with},
|
||||
CodeGenContext, CodeGenerator,
|
||||
},
|
||||
|
@ -1121,9 +1121,13 @@ fn polymorphic_print<'ctx>(
|
|||
fmt.push_str("range(");
|
||||
flush(ctx, generator, &mut fmt, &mut args);
|
||||
|
||||
let val = RangeValue::from_ptr_val(value.into_pointer_value(), None);
|
||||
let range = AnyObject { ty, value };
|
||||
let range = RangeObject::from_object(generator, ctx, range);
|
||||
|
||||
let (start, stop, step) = destructure_range(ctx, val);
|
||||
let (start, stop, step) = range.instance.destructure(generator, ctx);
|
||||
let start = start.value;
|
||||
let stop = stop.value;
|
||||
let step = step.value;
|
||||
|
||||
polymorphic_print(
|
||||
ctx,
|
||||
|
|
|
@ -3,10 +3,8 @@ use inkwell::values::{BasicValue, BasicValueEnum, IntValue};
|
|||
use inkwell::{FloatPredicate, IntPredicate, OptimizationLevel};
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::codegen::classes::RangeValue;
|
||||
use crate::codegen::expr::destructure_range;
|
||||
use crate::codegen::irrt::calculate_len_for_slice_range;
|
||||
use crate::codegen::object::ndarray::{NDArrayOut, ScalarOrNDArray};
|
||||
use crate::codegen::object::range::RangeObject;
|
||||
use crate::codegen::{extern_fns, irrt, llvm_intrinsics, CodeGenContext, CodeGenerator};
|
||||
use crate::toplevel::helper::PrimDef;
|
||||
use crate::typecheck::typedef::{Type, TypeEnum};
|
||||
|
@ -31,36 +29,35 @@ fn unsupported_type(ctx: &CodeGenContext<'_, '_>, fn_name: &str, tys: &[Type]) -
|
|||
pub fn call_len<'ctx, G: CodeGenerator + ?Sized>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
n: (Type, BasicValueEnum<'ctx>),
|
||||
(arg_ty, arg): (Type, BasicValueEnum<'ctx>),
|
||||
) -> Result<IntValue<'ctx>, String> {
|
||||
let (arg_ty, arg) = n;
|
||||
Ok(if ctx.unifier.unioned(arg_ty, ctx.primitives.range) {
|
||||
let arg = RangeValue::from_ptr_val(arg.into_pointer_value(), Some("range"));
|
||||
let (start, end, step) = destructure_range(ctx, arg);
|
||||
calculate_len_for_slice_range(generator, ctx, start, end, step)
|
||||
} else {
|
||||
let arg = AnyObject { ty: arg_ty, value: arg };
|
||||
let len: Instance<'ctx, Int<Int32>> = match &*ctx.unifier.get_ty(arg_ty) {
|
||||
TypeEnum::TTuple { .. } => {
|
||||
let tuple = TupleObject::from_object(ctx, arg);
|
||||
tuple.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let ndarray = NDArrayObject::from_object(generator, ctx, arg);
|
||||
ndarray.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.list.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let list = ListObject::from_object(generator, ctx, arg);
|
||||
list.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
_ => unsupported_type(ctx, "len", &[arg_ty]),
|
||||
};
|
||||
len.value
|
||||
})
|
||||
let arg = AnyObject { ty: arg_ty, value: arg };
|
||||
let len: Instance<'ctx, Int<Int32>> = match &*ctx.unifier.get_ty(arg_ty) {
|
||||
TypeEnum::TTuple { .. } => {
|
||||
let tuple = TupleObject::from_object(ctx, arg);
|
||||
tuple.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let range = RangeObject::from_object(generator, ctx, arg);
|
||||
range.len(generator, ctx)
|
||||
}
|
||||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let ndarray = NDArrayObject::from_object(generator, ctx, arg);
|
||||
ndarray.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.list.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let list = ListObject::from_object(generator, ctx, arg);
|
||||
list.len(generator, ctx).truncate(generator, ctx, Int32)
|
||||
}
|
||||
_ => unsupported_type(ctx, "len", &[arg_ty]),
|
||||
};
|
||||
Ok(len.value)
|
||||
}
|
||||
|
||||
/// Invokes the `int32` builtin function.
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
codegen::{
|
||||
classes::{
|
||||
ArrayLikeIndexer, ArrayLikeValue, ListType, ListValue, ProxyType, ProxyValue,
|
||||
RangeValue, UntypedArrayLikeAccessor,
|
||||
UntypedArrayLikeAccessor,
|
||||
},
|
||||
concrete_type::{ConcreteFuncArg, ConcreteTypeEnum, ConcreteTypeStore},
|
||||
gen_in_range_check, get_llvm_abi_type, get_llvm_type, get_va_count_arg_name,
|
||||
|
@ -49,6 +49,7 @@ use super::{
|
|||
object::{
|
||||
any::AnyObject,
|
||||
ndarray::{indexing::util::gen_ndarray_subscript_ndindices, NDArrayObject},
|
||||
range::RangeObject,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1080,18 +1081,6 @@ pub fn gen_call<'ctx, G: CodeGenerator>(
|
|||
Ok(ctx.build_call_or_invoke(fun_val, ¶m_vals, "call"))
|
||||
}
|
||||
|
||||
/// Generates three LLVM variables representing the start, stop, and step values of a [range] class
|
||||
/// respectively.
|
||||
pub fn destructure_range<'ctx>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
range: RangeValue<'ctx>,
|
||||
) -> (IntValue<'ctx>, IntValue<'ctx>, IntValue<'ctx>) {
|
||||
let start = range.load_start(ctx, None);
|
||||
let end = range.load_end(ctx, None);
|
||||
let step = range.load_step(ctx, None);
|
||||
(start, end, step)
|
||||
}
|
||||
|
||||
/// Allocates a List structure with the given [type][ty] and [length]. The name of the resulting
|
||||
/// LLVM value is `{name}.addr`, or `list.addr` if [name] is not specified.
|
||||
///
|
||||
|
@ -1166,8 +1155,14 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
|
|||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let iter_val = RangeValue::from_ptr_val(iter_val.into_pointer_value(), Some("range"));
|
||||
let (start, stop, step) = destructure_range(ctx, iter_val);
|
||||
let range = AnyObject { value: iter_val, ty: iter_ty };
|
||||
let range = RangeObject::from_object(generator, ctx, range);
|
||||
|
||||
let (start, stop, step) = range.instance.destructure(generator, ctx);
|
||||
let start = start.value;
|
||||
let stop = stop.value;
|
||||
let step = step.value;
|
||||
|
||||
let diff = ctx.builder.build_int_sub(stop, start, "diff").unwrap();
|
||||
// add 1 to the length as the value is rounded to zero
|
||||
// the length may be 1 more than the actual length if the division is exact, but the
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
codegen::classes::{ListType, ProxyType, RangeType},
|
||||
codegen::classes::{ListType, ProxyType},
|
||||
symbol_resolver::{StaticValue, SymbolResolver},
|
||||
toplevel::{helper::PrimDef, TopLevelContext, TopLevelDef},
|
||||
typecheck::{
|
||||
|
@ -26,7 +26,7 @@ use inkwell::{
|
|||
use itertools::Itertools;
|
||||
use model::*;
|
||||
use nac3parser::ast::{Location, Stmt, StrRef};
|
||||
use object::ndarray::NDArray;
|
||||
use object::{ndarray::NDArray, range::Range};
|
||||
use parking_lot::{Condvar, Mutex};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::{
|
||||
|
@ -721,7 +721,7 @@ pub fn gen_func_impl<
|
|||
Some(t) => t.as_basic_type_enum(),
|
||||
}
|
||||
}),
|
||||
(primitives.range, RangeType::new(context).as_base_type().into()),
|
||||
(primitives.range, Ptr(Range::<Int32>::default()).get_type(generator, context).into()),
|
||||
(primitives.exception, {
|
||||
let name = "Exception";
|
||||
if let Some(t) = module.get_struct_type(name) {
|
||||
|
|
|
@ -20,6 +20,19 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Ptr<Range<N>>> {
|
|||
pub fn step(&self, ctx: &CodeGenContext<'ctx, '_>) -> Instance<'ctx, Ptr<Int<N>>> {
|
||||
self.gep_const(ctx, 2)
|
||||
}
|
||||
|
||||
/// Convenience function to get the load the `(start, stop, step)` of this range.
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn destructure<G: CodeGenerator + ?Sized>(
|
||||
&self,
|
||||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
) -> (Instance<'ctx, Int<N>>, Instance<'ctx, Int<N>>, Instance<'ctx, Int<N>>) {
|
||||
let start = self.start(ctx).load(generator, ctx);
|
||||
let stop = self.stop(ctx).load(generator, ctx);
|
||||
let step = self.step(ctx).load(generator, ctx);
|
||||
(start, stop, step)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: `RangeObject` in the future will have range32, range64
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
use super::{
|
||||
super::symbol_resolver::ValueEnum,
|
||||
expr::destructure_range,
|
||||
irrt::{handle_slice_indices, list_slice_assignment},
|
||||
object::{
|
||||
any::AnyObject,
|
||||
ndarray::{
|
||||
indexing::util::gen_ndarray_subscript_ndindices, NDArrayObject, ScalarOrNDArray,
|
||||
},
|
||||
range::RangeObject,
|
||||
},
|
||||
CodeGenContext, CodeGenerator,
|
||||
};
|
||||
use crate::{
|
||||
codegen::{
|
||||
classes::{ArrayLikeIndexer, ArraySliceValue, ListValue, RangeValue},
|
||||
classes::{ArrayLikeIndexer, ArraySliceValue, ListValue},
|
||||
expr::gen_binop_expr,
|
||||
gen_in_range_check,
|
||||
},
|
||||
|
@ -497,7 +497,14 @@ pub fn gen_for<G: CodeGenerator>(
|
|||
TypeEnum::TObj { obj_id, .. }
|
||||
if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap() =>
|
||||
{
|
||||
let iter_val = RangeValue::from_ptr_val(iter_val.into_pointer_value(), Some("range"));
|
||||
let range = AnyObject { value: iter_val, ty: iter_ty };
|
||||
let range = RangeObject::from_object(generator, ctx, range);
|
||||
|
||||
let (start, stop, step) = range.instance.destructure(generator, ctx);
|
||||
let start = start.value;
|
||||
let stop = stop.value;
|
||||
let step = step.value;
|
||||
|
||||
// Internal variable for loop; Cannot be assigned
|
||||
let i = generator.gen_var_alloc(ctx, int32.into(), Some("for.i.addr"))?;
|
||||
// Variable declared in "target" expression of the loop; Can be reassigned *or* shadowed
|
||||
|
@ -506,7 +513,6 @@ pub fn gen_for<G: CodeGenerator>(
|
|||
else {
|
||||
unreachable!()
|
||||
};
|
||||
let (start, stop, step) = destructure_range(ctx, iter_val);
|
||||
|
||||
ctx.builder.build_store(i, start).unwrap();
|
||||
|
||||
|
|
|
@ -15,12 +15,12 @@ use strum::IntoEnumIterator;
|
|||
use crate::{
|
||||
codegen::{
|
||||
builtin_fns,
|
||||
classes::{ProxyValue, RangeValue},
|
||||
model::*,
|
||||
numpy::*,
|
||||
object::{
|
||||
any::AnyObject,
|
||||
ndarray::{shape_util::parse_numpy_int_sequence, NDArrayObject},
|
||||
range::RangeObject,
|
||||
},
|
||||
stmt::exn_constructor,
|
||||
},
|
||||
|
@ -717,9 +717,10 @@ impl<'a> BuiltinBuilder<'a> {
|
|||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||
|ctx, obj, _, args, generator| {
|
||||
let (zelf_ty, zelf) = obj.unwrap();
|
||||
let zelf =
|
||||
zelf.to_basic_value_enum(ctx, generator, zelf_ty)?.into_pointer_value();
|
||||
let zelf = RangeValue::from_ptr_val(zelf, Some("range"));
|
||||
let zelf = zelf.to_basic_value_enum(ctx, generator, zelf_ty)?;
|
||||
|
||||
let zelf = AnyObject { ty: zelf_ty, value: zelf };
|
||||
let zelf = RangeObject::from_object(generator, ctx, zelf);
|
||||
|
||||
let mut start = None;
|
||||
let mut stop = None;
|
||||
|
@ -802,11 +803,14 @@ impl<'a> BuiltinBuilder<'a> {
|
|||
});
|
||||
let start = start.unwrap_or_else(|| int32.const_zero());
|
||||
|
||||
zelf.store_start(ctx, start);
|
||||
zelf.store_end(ctx, stop);
|
||||
zelf.store_step(ctx, step);
|
||||
let start = Int(Int32).believe_value(start);
|
||||
let stop = Int(Int32).believe_value(stop);
|
||||
let step = Int(Int32).believe_value(step);
|
||||
zelf.instance.start(ctx).store(ctx, start);
|
||||
zelf.instance.stop(ctx).store(ctx, stop);
|
||||
zelf.instance.step(ctx).store(ctx, step);
|
||||
|
||||
Ok(Some(zelf.as_base_value().into()))
|
||||
Ok(Some(zelf.instance.value.as_basic_value_enum()))
|
||||
},
|
||||
)))),
|
||||
loc: None,
|
||||
|
|
Loading…
Reference in New Issue