Skip to content

Commit

Permalink
feat: in-place array iteration
Browse files Browse the repository at this point in the history
  • Loading branch information
jac3km4 committed Aug 12, 2024
1 parent d34f65b commit dc6bc31
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 21 deletions.
46 changes: 34 additions & 12 deletions compiler/src/sugar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::error::{Cause, Error, ResultSpan};
use crate::scope::{Reference, Scope, TypeId, Value};
use crate::symbol::{FunctionSignature, FunctionSignatureBuilder};
use crate::transform::ExprTransformer;
use crate::typechecker::{type_of, Callable, TypedAst, TypedExpr};
use crate::typechecker::{type_of, Callable, TypedAst, TypedExpr, TypedExprExt};

pub struct Desugar<'a> {
pool: &'a mut ConstantPool,
Expand Down Expand Up @@ -146,17 +146,44 @@ impl<'a> ExprTransformer<TypedAst> for Desugar<'a> {
let mut seq = self.on_seq(seq)?;

let array = self.on_expr(array)?;
let arr_type = type_of(&array, self.scope, self.pool)?;
let arr_local = self.fresh_local(&arr_type).with_span(span)?;
let array_type = type_of(&array, self.scope, self.pool)?;
let array_ref_type = TypeId::ScriptRef(array_type.clone().into());
let array_local = self.fresh_local(&array_ref_type).with_span(span)?;
let array_deref = || {
Expr::Call(
Callable::Intrinsic(Intrinsic::Deref, array_type.clone()),
[].into(),
[Expr::Ident(array_local.clone(), span)].into(),
span,
)
};

let counter_type = self.scope.resolve_type(&TypeName::INT32, self.pool).with_span(span)?;
let counter_local = self.fresh_local(&counter_type).with_span(span)?;

let array_lvalue = if array.is_prvalue() {
let tmp_local = self.fresh_local(&array_type).with_span(span)?;
self.add_prefix(Expr::Assign(
Box::new(Expr::Ident(tmp_local.clone(), span)),
Box::new(array),
span,
));
Expr::Ident(tmp_local, span)
} else {
array
};

self.add_prefix(Expr::Assign(
Box::new(Expr::Ident(arr_local.clone(), span)),
Box::new(array),
Box::new(Expr::Ident(array_local.clone(), span)),
Box::new(Expr::Call(
Callable::Intrinsic(Intrinsic::AsRef, array_ref_type),
[].into(),
[array_lvalue].into(),
span,
)),
span,
));

self.add_prefix(Expr::Assign(
Box::new(Expr::Ident(counter_local.clone(), span)),
Box::new(Expr::Constant(Constant::I32(0), span)),
Expand All @@ -181,20 +208,15 @@ impl<'a> ExprTransformer<TypedAst> for Desugar<'a> {
[].into(),
[
Expr::Ident(counter_local.clone(), span),
Expr::Call(
array_size,
[].into(),
[Expr::Ident(arr_local.clone(), span)].into(),
span,
),
Expr::Call(array_size, [].into(), [array_deref()].into(), span),
]
.into(),
span,
);
let assign_iter_value = Expr::Assign(
Box::new(Expr::Ident(Reference::Value(Value::Local(name)), span)),
Box::new(Expr::ArrayElem(
Box::new(Expr::Ident(arr_local, span)),
Box::new(array_deref()),
Box::new(Expr::Ident(counter_local.clone(), span)),
span,
)),
Expand Down
78 changes: 69 additions & 9 deletions compiler/tests/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,33 +146,93 @@ fn compile_for_loop() {

let check = check_code![
mem!(ArrayResize(int_array_type)),
mem!(Local(tmp_array)),
mem!(Local(array)),
pat!(U64Const(2)),
pat!(Assign),
mem!(ArrayElement(int_array_type)),
mem!(Local(tmp_array)),
mem!(Local(array)),
pat!(U64Const(0)),
pat!(I32Const(0)),
pat!(Assign),
mem!(ArrayElement(int_array_type)),
mem!(Local(tmp_array)),
mem!(Local(array)),
pat!(U64Const(1)),
pat!(I32Const(1)),
pat!(Assign),
mem!(Local(array_ref)),
mem!(AsRef(int_array_type)),
mem!(Local(array)),
pat!(Assign),
mem!(Local(counter)),
pat!(I32Const(0)),
pat!(JumpIfFalse(Offset { value: 168 })),
pat!(InvokeStatic(Offset { value: 52 }, 1, _, 0)),
mem!(Local(counter)),
mem!(ArraySize(int_type)),
mem!(Deref(int_array_type)),
mem!(Local(array_ref)),
pat!(ParamEnd),
pat!(Assign),
mem!(Local(i)),
mem!(ArrayElement(int_type)),
mem!(Deref(int_array_type)),
mem!(Local(array_ref)),
mem!(Local(counter)),
pat!(InvokeStatic(Offset { value: 34 }, 1, _, 0)),
pat!(ToString(_)),
mem!(Local(i)),
pat!(ParamEnd),
pat!(InvokeStatic(Offset { value: 30 }, 1, _, 0)),
mem!(Local(counter)),
pat!(I32Const(1)),
pat!(ParamEnd),
pat!(Jump(Offset { value: -165 })),
pat!(Nop)
];
TestContext::compiled(vec![sources]).unwrap().run("Testing", check);
}

#[test]
fn compile_for_loop_with_tmp_array() {
let sources = "
func Testing() {
for i in GetArray() {
Log(ToString(i));
}
}
func GetArray() -> array<Int32> {
return [0, 1];
}
native func Log(str: String)
native func OperatorAssignAdd(out l: Int32, r: Int32) -> Int32
native func OperatorLess(l: Int32, r: Int32) -> Bool
";

let check = check_code![
pat!(Assign),
mem!(Local(tmp_array)),
pat!(InvokeStatic(Offset { value: 16 }, 1, _, 0)),
pat!(ParamEnd),
pat!(Assign),
mem!(Local(array_ref)),
mem!(AsRef(int_array_type)),
mem!(Local(tmp_array)),
pat!(Assign),
mem!(Local(counter)),
pat!(I32Const(0)),
pat!(JumpIfFalse(Offset { value: 150 })),
pat!(InvokeStatic(Offset { value: 43 }, 1, _, 0)),
pat!(JumpIfFalse(Offset { value: 168 })),
pat!(InvokeStatic(Offset { value: 52 }, 1, _, 0)),
mem!(Local(counter)),
mem!(ArraySize(elem_type)),
mem!(Local(array)),
mem!(ArraySize(int_type)),
mem!(Deref(int_array_type)),
mem!(Local(array_ref)),
pat!(ParamEnd),
pat!(Assign),
mem!(Local(i)),
mem!(ArrayElement(elem_type)),
mem!(ArrayElement(int_type)),
mem!(Deref(int_array_type)),
mem!(Local(array)),
mem!(Local(counter)),
pat!(InvokeStatic(Offset { value: 34 }, 1, _, 0)),
Expand All @@ -183,7 +243,7 @@ fn compile_for_loop() {
mem!(Local(counter)),
pat!(I32Const(1)),
pat!(ParamEnd),
pat!(Jump(Offset { value: -147 })),
pat!(Jump(Offset { value: -165 })),
pat!(Nop)
];
TestContext::compiled(vec![sources]).unwrap().run("Testing", check);
Expand Down
1 change: 1 addition & 0 deletions compiler/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ impl TestContext {
Ok(res)
}

#[track_caller]
pub fn match_index(&mut self, idx: PoolIndex<Definition>, name: &str) {
match self.indexes.get(name) {
Some(val) if *val == idx => (),
Expand Down

0 comments on commit dc6bc31

Please sign in to comment.