Skip to content
This repository was archived by the owner on Jun 10, 2024. It is now read-only.

Commit 72fd4c9

Browse files
committed
Add basic matching, various improvements
1 parent 2bb7d11 commit 72fd4c9

File tree

5 files changed

+87
-333
lines changed

5 files changed

+87
-333
lines changed

liblumen_eir_interpreter/fib.erl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
run() ->
66
N = fib(8).
77

8-
fib(X) when X < 2 -> 1;
9-
fib(X) -> fib(X - 1) + fib(X-2).
8+
fib(0) -> 0;
9+
fib(1) -> 1;
10+
fib(X) -> fib(X-1) + fib(X-2).

liblumen_eir_interpreter/src/code.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,37 @@ use liblumen_alloc::erts::exception::runtime::{ Exception, Class };
1414
use crate::exec::CallExecutor;
1515

1616
pub fn return_throw(arc_process: &Arc<ProcessControlBlock>) -> Result {
17-
let class_term = arc_process.stack_pop().unwrap();
18-
let reason_term = arc_process.stack_pop().unwrap();
19-
let trace_term = arc_process.stack_pop().unwrap();
20-
21-
let class: Atom = class_term.try_into().unwrap();
22-
let class = match class.name() {
23-
"EXIT" => Class::Exit,
24-
_ => unreachable!(),
25-
};
26-
27-
let exc = Exception {
28-
class,
29-
reason: reason_term,
30-
stacktrace: Some(trace_term),
31-
file: "",
32-
line: 0,
33-
column: 0,
34-
};
35-
result_from_exception(arc_process, exc.into())
17+
let module_term = arc_process.stack_pop().unwrap();
18+
let function_term = arc_process.stack_pop().unwrap();
19+
let argument_list = arc_process.stack_pop().unwrap();
20+
21+
panic!("{:?}", argument_list);
22+
23+
//let class: Atom = class_term.try_into().unwrap();
24+
//let class = match class.name() {
25+
// "EXIT" => Class::Exit,
26+
// k => unreachable!("{:?}", k),
27+
//};
28+
29+
//let exc = Exception {
30+
// class,
31+
// reason: reason_term,
32+
// stacktrace: Some(trace_term),
33+
// file: "",
34+
// line: 0,
35+
// column: 0,
36+
//};
37+
//result_from_exception(arc_process, exc.into())
3638
}
3739

3840
pub fn return_ok(arc_process: &Arc<ProcessControlBlock>) -> Result {
39-
let result_term = arc_process.stack_pop().unwrap();
40-
arc_process.return_from_call(result_term)?;
41+
let _module_term = arc_process.stack_pop().unwrap();
42+
let _function_term = arc_process.stack_pop().unwrap();
43+
let argument_list = arc_process.stack_pop().unwrap();
44+
45+
println!("PROCESS EXIT NORMAL WITH: {:?}", argument_list);
46+
47+
arc_process.return_from_call(argument_list)?;
4148
ProcessControlBlock::call_code(arc_process)
4249
}
4350

@@ -51,6 +58,8 @@ pub fn interpreter_mfa_code(arc_process: &Arc<ProcessControlBlock>) -> Result {
5158
let function_term = arc_process.stack_pop().unwrap();
5259
let argument_list = arc_process.stack_pop().unwrap();
5360

61+
//let mfa = arc_process.current_module_function_arity().unwrap();
62+
5463
let module: Atom = module_term.try_into().unwrap();
5564
let function: Atom = function_term.try_into().unwrap();
5665

liblumen_eir_interpreter/src/exec/match.rs

Lines changed: 28 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -1,185 +1,53 @@
1-
use libeir_ir::{ Block, MatchKind, BasicType, BinaryEntrySpecifier, Endianness };
1+
use std::convert::TryInto;
2+
use std::sync::Arc;
23

3-
use libeir_util::binary::{ BitCarrier };
4-
use libeir_util::binary::{ BitVec, BitSlice, carrier_to_integer, Endian };
4+
use libeir_ir::{ Block, MatchKind, PrimOpKind, BasicType,
5+
BinaryEntrySpecifier, Endianness };
56

6-
use crate::{ Term };
7-
use crate::module::ErlangFunction;
8-
use crate::term::ErlExactEq;
7+
use lumen_runtime::otp::erlang;
8+
use liblumen_alloc::erts::term::{ Term, TypedTerm, Tuple, Atom, Integer, Closure,
9+
AsTerm, atom_unchecked };
10+
use liblumen_alloc::erts::process::ProcessControlBlock;
11+
use liblumen_alloc::erts::exception::system;
912

10-
use super::{ CallExecutor, TermCall };
13+
use crate::module::ErlangFunction;
14+
use super::{ CallExecutor, OpResult };
1115

1216
pub fn match_op(
1317
exec: &mut CallExecutor,
18+
proc: &Arc<ProcessControlBlock>,
1419
fun: &ErlangFunction,
1520
branches: &[MatchKind],
1621
block: Block
17-
) -> TermCall
22+
) -> std::result::Result<OpResult, system::Exception>
1823
{
1924
let reads = fun.fun.block_reads(block);
2025

21-
let branches_elems = Term::as_value_list(
22-
&exec.make_term(fun, reads[0]));
26+
let branches_prim = fun.fun.value_primop(reads[0]).unwrap();
27+
assert!(fun.fun.primop_kind(branches_prim) == &PrimOpKind::ValueList);
28+
let branches_dests = fun.fun.primop_reads(branches_prim);
29+
30+
let unpack_term = exec.make_term(proc, fun, reads[1]).unwrap();
2331

24-
let unpack_term = exec.make_term(fun, reads[1]);
32+
for (idx, (kind, branch)) in branches.iter()
33+
.zip(branches_dests.iter()).enumerate()
34+
{
35+
let branch_arg_prim = fun.fun.value_primop(reads[idx + 2]).unwrap();
36+
assert!(fun.fun.primop_kind(branch_arg_prim) == &PrimOpKind::ValueList);
37+
let branch_args = fun.fun.primop_reads(branch_arg_prim);
2538

26-
//println!("MATCH START {:?}", unpack_term);
27-
for (idx, kind) in branches.iter().enumerate() {
28-
let branch_args = Term::as_value_list(
29-
&exec.make_term(fun, reads[idx + 2]));
30-
//println!("MATCH KIND {:?} {:?}", kind, branch_args);
3139
match kind {
3240
MatchKind::Value => {
3341
assert!(branch_args.len() == 1);
34-
if unpack_term.erl_exact_eq(&*branch_args[0]) {
35-
return TermCall {
36-
fun: branches_elems[idx].clone(),
37-
args: vec![],
38-
};
39-
}
40-
}
41-
MatchKind::ListCell => {
42-
assert!(branch_args.len() == 0);
43-
match &*unpack_term {
44-
Term::ListCell(head, tail) => {
45-
return TermCall {
46-
fun: branches_elems[idx].clone(),
47-
args: vec![head.clone(), tail.clone()],
48-
};
49-
}
50-
_ => (),
51-
}
52-
}
53-
MatchKind::Tuple(len) => {
54-
assert!(branch_args.len() == 0);
55-
match &*unpack_term {
56-
Term::Tuple(elems) if elems.len() == *len => {
57-
return TermCall {
58-
fun: branches_elems[idx].clone(),
59-
args: elems.clone(),
60-
};
61-
}
62-
_ => (),
63-
}
64-
}
65-
MatchKind::Type(BasicType::Map) => {
66-
assert!(branch_args.len() == 0);
67-
match &*unpack_term {
68-
Term::Map(_) => {
69-
return TermCall {
70-
fun: branches_elems[idx].clone(),
71-
args: vec![],
72-
};
73-
}
74-
_ => (),
75-
}
76-
}
77-
MatchKind::MapItem => {
78-
assert!(branch_args.len() == 1);
79-
match &*unpack_term {
80-
Term::Map(map) => {
81-
if let Some(v) = map.get(&branch_args[0]) {
82-
return TermCall {
83-
fun: branches_elems[idx].clone(),
84-
args: vec![v.clone()],
85-
};
86-
}
87-
}
88-
_ => unreachable!(),
89-
}
90-
}
91-
MatchKind::Binary(BinaryEntrySpecifier::Integer {
92-
unit, endianness, signed
93-
}) => {
94-
let size = branch_args[0].as_usize().unwrap();
95-
let bit_len = (*unit as usize) * size;
96-
97-
let ret = match &*unpack_term {
98-
Term::Binary(bin) => {
99-
if (bin.len() * 8) < bit_len { continue; }
100-
101-
let int_slice = BitSlice::with_offset_length(
102-
&**bin, 0, bit_len);
103-
let endian = match *endianness {
104-
Endianness::Big => Endian::Big,
105-
Endianness::Little => Endian::Little,
106-
Endianness::Native => Endian::Big,
107-
};
108-
let int = carrier_to_integer(int_slice, *signed, endian);
109-
110-
TermCall {
111-
fun: branches_elems[idx].clone(),
112-
args: vec![
113-
Term::Integer(int).into(),
114-
Term::BinarySlice {
115-
buf: bin.clone(),
116-
bit_offset: bit_len,
117-
bit_length: bin.bit_len() - bit_len,
118-
}.into(),
119-
],
120-
}
121-
},
122-
Term::BinarySlice { buf, bit_offset, bit_length } => {
123-
if *bit_length < bit_len { continue; }
124-
125-
let int_slice = BitSlice::with_offset_length(
126-
&**buf, *bit_offset, bit_len);
127-
let endian = match *endianness {
128-
Endianness::Big => Endian::Big,
129-
Endianness::Little => Endian::Little,
130-
Endianness::Native => Endian::Big,
131-
};
132-
let int = carrier_to_integer(int_slice, *signed, endian);
133-
134-
TermCall {
135-
fun: branches_elems[idx].clone(),
136-
args: vec![
137-
Term::Integer(int).into(),
138-
Term::BinarySlice {
139-
buf: buf.clone(),
140-
bit_offset: *bit_offset + bit_len,
141-
bit_length: *bit_length - bit_len,
142-
}.into(),
143-
],
144-
}
145-
},
146-
_ => continue,
147-
};
148-
return ret;
149-
}
150-
MatchKind::Binary(BinaryEntrySpecifier::Bytes { unit: 8 }) => {
151-
match &*unpack_term {
152-
Term::Binary(bin) => {
153-
if bin.bit_len() % 8 != 0 { continue; }
154-
155-
return TermCall {
156-
fun: branches_elems[idx].clone(),
157-
args: vec![
158-
unpack_term.clone(),
159-
Term::Binary(BitVec::new().into()).into(),
160-
],
161-
};
162-
}
163-
Term::BinarySlice { bit_length, .. } => {
164-
if *bit_length % 8 != 0 { continue; }
42+
let rhs = exec.make_term(proc, fun, branch_args[0]).unwrap();
16543

166-
return TermCall {
167-
fun: branches_elems[idx].clone(),
168-
args: vec![
169-
unpack_term.clone(),
170-
Term::Binary(BitVec::new().into()).into(),
171-
],
172-
};
173-
}
174-
_ => (),
44+
if unpack_term.exactly_eq(&rhs) {
45+
return exec.val_call(proc, fun, *branch);
17546
}
17647
}
17748
MatchKind::Wildcard => {
17849
assert!(branch_args.len() == 0);
179-
return TermCall {
180-
fun: branches_elems[idx].clone(),
181-
args: vec![],
182-
};
50+
return exec.val_call(proc, fun, *branch);
18351
}
18452
kind => unimplemented!("{:?}", kind),
18553
}

0 commit comments

Comments
 (0)