Skip to content

Commit a37ab72

Browse files
committed
refactor: rename package and update imports to use new structure; add list comprehension support
1 parent 1a22716 commit a37ab72

20 files changed

Lines changed: 360 additions & 33 deletions

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# MoonBit Eval
22

3-
[![Version](https://img.shields.io/badge/dynamic/json?url=https%3A//mooncakes.io/assets/oboard/moonbit-eval/resource.json&query=%24.meta_info.version&label=mooncakes&color=yellow)](https://mooncakes.io/docs/oboard/moonbit-eval)
4-
[![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/oboard/moonbit-eval/check.yaml)](https://github.com/oboard/moonbit-eval/actions/workflows/check.yaml)
5-
[![License](https://img.shields.io/github/license/oboard/moonbit-eval)](https://github.com/oboard/moonbit-eval/blob/main/LICENSE)
3+
[![Version](https://img.shields.io/badge/dynamic/json?url=https%3A//mooncakes.io/assets/oboard/eval/resource.json&query=%24.meta_info.version&label=mooncakes&color=yellow)](https://mooncakes.io/docs/oboard/eval)
4+
[![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/oboard/eval/check.yaml)](https://github.com/oboard/eval/actions/workflows/check.yaml)
5+
[![License](https://img.shields.io/github/license/oboard/eval)](https://github.com/oboard/eval/blob/main/LICENSE)
66

77
## Demo
88
🚀 **[REPL Demo](https://github.com/oboard/moonbit-repl/releases/)**

example/moon.pkg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
"oboard/moonbit-eval" @eval,
2+
"oboard/eval" @eval,
33
}
44

55
options(

example/pkg.generated.mbti

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Generated using `moon info`, DON'T EDIT IT
2-
package "oboard/moonbit-eval/example"
2+
package "oboard/eval/example"
33

44
// Values
55

export.mbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn eval_result_to_string(result : EvalResult) -> String {
2323

2424
///|
2525
pub fn code_to_ast(code : String) -> String {
26-
match @front.parse_code_to_impl(code) {
26+
match @front.parse_code_to_impl(@core.normalize_v092_syntax(code)) {
2727
Ok(i) => i.to_json().stringify()
2828
Err(msg) => msg
2929
}

interpreter/core/expression_visitors.mbt

Lines changed: 131 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,101 @@ fn ClosureInterpreter::visit_tuple(
134134
Tuple(evaluated_values)
135135
}
136136

137+
///|
138+
fn ClosureInterpreter::syntax_iterable_to_iter(
139+
self : ClosureInterpreter,
140+
expr : @syntax.Expr,
141+
) -> Iter[RuntimeValue] raise ControlFlow {
142+
match expr {
143+
Infix(op~, lhs~, rhs~, ..) =>
144+
match op.name {
145+
Ident(name="..<") => {
146+
let start_val = self.visit(lhs)
147+
let end_val = self.visit(rhs)
148+
match (start_val, end_val) {
149+
(Int(start, ..), Int(end, ..)) =>
150+
start.until(end).map(fn(i) { Int(i, raw=None) })
151+
_ => Iter::empty()
152+
}
153+
}
154+
Ident(name="..=") => {
155+
let start_val = self.visit(lhs)
156+
let end_val = self.visit(rhs)
157+
match (start_val, end_val) {
158+
(Int(start, ..), Int(end, ..)) =>
159+
start.until(end, inclusive=true).map(fn(i) { Int(i, raw=None) })
160+
_ => Iter::empty()
161+
}
162+
}
163+
_ => self.visit_iterable_expr(expr)
164+
}
165+
_ => self.visit_iterable_expr(expr)
166+
}
167+
}
168+
169+
///|
170+
fn ClosureInterpreter::visit_iterable_expr(
171+
self : ClosureInterpreter,
172+
expr : @syntax.Expr,
173+
) -> Iter[RuntimeValue] raise ControlFlow {
174+
match self.visit(expr) {
175+
Iter(iter) => iter
176+
value =>
177+
match self.method_call(value, "iter", @list.new()) {
178+
Iter(iter) => iter
179+
_ => self.error("iter method not found")
180+
}
181+
}
182+
}
183+
184+
///|
185+
fn ClosureInterpreter::visit_for_each_as_array(
186+
self : ClosureInterpreter,
187+
binders : @list.List[@syntax.Binder?],
188+
expr : @syntax.Expr,
189+
body : @syntax.Expr,
190+
) -> RuntimeValue raise ControlFlow {
191+
let result : Array[RuntimeValue] = []
192+
let binder_count = binders.length()
193+
for value in self.syntax_iterable_to_iter(expr) {
194+
self.push_scope(RuntimeLocation::ControlFlow("list comprehension"))
195+
defer self.pop_scope()
196+
match binders {
197+
@list.More(Some(binder), tail=@list.Empty) =>
198+
self.current_pkg.env.set(binder.name, value)
199+
@list.More(
200+
Some(binder1),
201+
tail=@list.More(Some(binder2), tail=@list.Empty)
202+
) =>
203+
match value {
204+
Tuple([first, second]) => {
205+
self.current_pkg.env.set(binder1.name, first)
206+
self.current_pkg.env.set(binder2.name, second)
207+
}
208+
_ => ()
209+
}
210+
_ => if binder_count == 0 { () }
211+
}
212+
let value = self.visit(body) catch {
213+
Continue(_) => continue
214+
e => raise e
215+
}
216+
result.push(value)
217+
}
218+
Array(result)
219+
}
220+
137221
///|
138222
/// 处理数组表达式
139223
fn ClosureInterpreter::visit_array(
140224
self : ClosureInterpreter,
141225
exprs : @list.List[@syntax.Expr],
142226
) -> RuntimeValue raise ControlFlow {
227+
match exprs {
228+
@list.More(ForEach(binders~, expr~, body~, ..), tail=@list.Empty) =>
229+
return self.visit_for_each_as_array(binders, expr, body)
230+
_ => ()
231+
}
143232
let result_values = []
144233
for expr in exprs {
145234
match expr {
@@ -190,6 +279,40 @@ fn ClosureInterpreter::call_struct_constr(
190279
}
191280
}
192281

282+
///|
283+
fn ClosureInterpreter::call_struct_constr_with_type_name(
284+
self : ClosureInterpreter,
285+
type_name : @syntax.TypeName,
286+
constr_name : String,
287+
field_values : @list.List[@syntax.Argument],
288+
) -> RuntimeValue? raise ControlFlow {
289+
self.with_ident(type_name.name, (pkg, name) => {
290+
let ty = pkg.find_static_type(name)
291+
if pkg.struct_constrs.get(name) is Some(method_name) {
292+
let method_name = if constr_name == "" {
293+
method_name
294+
} else {
295+
constr_name
296+
}
297+
Some(self.execute_static_method_call(ty, method_name, field_values))
298+
} else {
299+
None
300+
}
301+
})
302+
}
303+
304+
///|
305+
fn ClosureInterpreter::constructor_runtime_package(
306+
self : ClosureInterpreter,
307+
constr : @syntax.Constructor,
308+
) -> RuntimePackage {
309+
match constr.extra_info {
310+
Package(pkg_name) => self.find_pkg(pkg_name)
311+
TypeName(type_name) => self.with_ident(type_name.name, (pkg, _) => pkg)
312+
NoExtraInfo => self.current_pkg
313+
}
314+
}
315+
193316
///|
194317
/// 处理函数调用
195318
fn ClosureInterpreter::visit_apply(
@@ -203,16 +326,15 @@ fn ClosureInterpreter::visit_apply(
203326
// 处理构造函数调用,如 Some(5)
204327
Constr(constr~, ..) => {
205328
match constr.extra_info {
206-
TypeName(type_name) => {
207-
let constr_type_name = match type_name.name {
208-
Ident(name~) => name
209-
Dot(id~, ..) => id
210-
}
211-
if self.call_struct_constr(None, constr_type_name, args)
329+
TypeName(type_name) =>
330+
if self.call_struct_constr_with_type_name(
331+
type_name,
332+
constr.name.name,
333+
args,
334+
)
212335
is Some(result) {
213336
return result
214337
}
215-
}
216338
Package(pkg_name) if self.call_struct_constr(
217339
Some(pkg_name),
218340
constr.name.name,
@@ -245,9 +367,10 @@ fn ClosureInterpreter::visit_apply(
245367
})
246368
.to_array()
247369
let constr_name = constr.name.name
370+
let pkg = self.constructor_runtime_package(constr)
248371
Constructor({
249372
val: { name: constr_name, fields },
250-
ty: self.current_pkg.find_static_type(constr_name),
373+
ty: pkg.find_static_type(constr_name),
251374
})
252375
}
253376
// 处理静态方法调用,如 Bool::default()

interpreter/core/interpreter.mbt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub fn ClosureInterpreter::top_eval(
7272
self : ClosureInterpreter,
7373
code : String,
7474
) -> Unit {
75+
let code = normalize_v092_syntax(code)
7576
let (impls, _diagnostics) = @moonbitlang/parser.parse_string(
7677
code,
7778
parser=Handrolled,
@@ -793,13 +794,11 @@ pub fn ClosureInterpreter::visit(
793794
let name = constr.name.name
794795
match constr.extra_info {
795796
TypeName(ty_name) =>
796-
self.with_ident(ty_name.name, (_env, _name) => {
797-
self.current_pkg.cons(name, [])
798-
})
797+
self.with_ident(ty_name.name, (pkg, _name) => pkg.cons(name, []))
799798
Package(pkg) =>
800799
self.find_pkg(pkg).env
801800
.find(name)
802-
.unwrap_or(self.current_pkg.cons(name, []))
801+
.unwrap_or(self.find_pkg(pkg).cons(name, []))
803802
_ =>
804803
self.current_pkg.env
805804
.find(name)

interpreter/core/moon.pkg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ import {
1616
"moonbitlang/parser/tokens",
1717
"moonbitlang/parser/attribute",
1818
"moonbitlang/x/fs",
19-
"oboard/moonbit-eval/interpreter/host" @host,
19+
"oboard/eval/interpreter/host" @host,
2020
}

interpreter/core/pattern_matching.mbt

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,39 @@ fn format_pattern(pattern : @syntax.Pattern) -> String {
151151
}
152152
}
153153

154+
///|
155+
fn ClosureInterpreter::constructor_pattern_matches_type(
156+
self : ClosureInterpreter,
157+
value_type : RuntimeType,
158+
constr : @syntax.Constructor,
159+
) -> Bool {
160+
match constr.extra_info {
161+
TypeName(type_name) =>
162+
self.with_ident(type_name.name, (pkg, name) => {
163+
let expected_type = pkg.find_static_type(name)
164+
if value_type == expected_type {
165+
true
166+
} else {
167+
match (value_type, expected_type) {
168+
(Any, _) | (_, Any) => true
169+
(Object(name=value_name, ..), Object(name=expected_name, ..)) =>
170+
value_name == expected_name
171+
(Name(name=value_name, ..), Name(name=expected_name, ..)) =>
172+
value_name == expected_name
173+
_ => false
174+
}
175+
}
176+
})
177+
Package(pkg_name) =>
178+
match value_type {
179+
Object(pkg~, ..) => pkg.name == self.find_pkg(pkg_name).name
180+
Name(pkg~, ..) => pkg.name == self.find_pkg(pkg_name).name
181+
_ => false
182+
}
183+
NoExtraInfo => true
184+
}
185+
}
186+
154187
///|
155188
/// 检查模式是否匹配给定的运行时值
156189
pub fn ClosureInterpreter::match_case(
@@ -295,8 +328,9 @@ pub fn ClosureInterpreter::match_case(
295328
// Constructor模式匹配
296329
Constr(constr~, args=pattern_args, ..) =>
297330
match value {
298-
Constructor({ val: { name, fields }, .. }) =>
299-
if name == constr.name.name {
331+
Constructor({ val: { name, fields }, ty }) =>
332+
if name == constr.name.name &&
333+
self.constructor_pattern_matches_type(ty, constr) {
300334
// 检查参数匹配
301335
match pattern_args {
302336
// 无参数的构造函数,只需要名称匹配

interpreter/core/pkg.generated.mbti

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Generated using `moon info`, DON'T EDIT IT
2-
package "oboard/moonbit-eval/interpreter/core"
2+
package "oboard/eval/interpreter/core"
33

44
import {
55
"moonbitlang/core/bigint",
@@ -46,6 +46,8 @@ pub fn manualUnescape(StringView, StringBuilder) -> Unit
4646

4747
pub let map_methods : Map[String, (RuntimeFunctionContext) -> RuntimeValue raise ControlFlow]
4848

49+
pub fn normalize_v092_syntax(String) -> String
50+
4951
pub let option_methods : Map[String, (RuntimeFunctionContext) -> RuntimeValue raise ControlFlow]
5052

5153
pub fn parse_code_to_expr(String) -> Result[@syntax.Expr, String]

0 commit comments

Comments
 (0)