feat: functions with formal parameters
This commit is contained in:
@@ -32,8 +32,6 @@ pub enum OpCode {
|
|||||||
/// [ .. func args @ .. ] consume (`arity` + 2) elements, call `func` with args` of length `arity`
|
/// [ .. func args @ .. ] consume (`arity` + 2) elements, call `func` with args` of length `arity`
|
||||||
/// Example: __add 1 2 => [ LookUp("__add") Const(1) Const(2) Call(2) ]
|
/// Example: __add 1 2 => [ LookUp("__add") Const(1) Const(2) Call(2) ]
|
||||||
Call { arity: usize },
|
Call { arity: usize },
|
||||||
/// return a value
|
|
||||||
Ret,
|
|
||||||
/// make a function
|
/// make a function
|
||||||
Func { idx: ThunkIdx },
|
Func { idx: ThunkIdx },
|
||||||
/// push param `sym` into TOS
|
/// push param `sym` into TOS
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ pub struct Catchable {
|
|||||||
msg: Option<String>,
|
msg: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, Constructor)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Constructor)]
|
||||||
pub struct Symbol(EcoString);
|
pub struct Symbol(EcoString);
|
||||||
|
|
||||||
impl<T: Into<EcoString>> From<T> for Symbol {
|
impl<T: Into<EcoString>> From<T> for Symbol {
|
||||||
@@ -24,3 +24,12 @@ impl Deref for Symbol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Symbol {
|
||||||
|
pub fn into_inner(self) -> EcoString {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_inner(&self) -> &EcoString {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,9 +43,13 @@ impl AttrSet {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_data(self) -> HashTrieMapSync<Symbol, Value> {
|
pub fn into_inner(self) -> HashTrieMapSync<Symbol, Value> {
|
||||||
self.data
|
self.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_inner(&self) -> &HashTrieMapSync<Symbol, Value> {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToPublic for AttrSet {
|
impl ToPublic for AttrSet {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use ecow::EcoString;
|
use ecow::EcoString;
|
||||||
|
use itertools::Itertools;
|
||||||
use rpds::HashTrieMap;
|
use rpds::HashTrieMap;
|
||||||
|
|
||||||
use crate::bytecode::{OpCodes, ThunkIdx};
|
use crate::bytecode::{OpCodes, ThunkIdx};
|
||||||
use crate::ty::internal::Value;
|
use crate::ty::internal::{Thunk, Value};
|
||||||
|
|
||||||
use crate::vm::{LockedEnv, VM};
|
use crate::vm::{LockedEnv, VM};
|
||||||
|
|
||||||
@@ -39,7 +40,38 @@ impl Func {
|
|||||||
|
|
||||||
match self.param.unwrap() {
|
match self.param.unwrap() {
|
||||||
Ident(ident) => env.enter(HashTrieMap::new_sync().insert(ident.into(), arg)),
|
Ident(ident) => env.enter(HashTrieMap::new_sync().insert(ident.into(), arg)),
|
||||||
Formals { .. } => todo!()
|
Formals {
|
||||||
|
formals,
|
||||||
|
ellipsis,
|
||||||
|
alias,
|
||||||
|
} => {
|
||||||
|
let arg = arg.unwrap_attr_set();
|
||||||
|
let mut new = HashTrieMap::new_sync();
|
||||||
|
if !ellipsis
|
||||||
|
&& arg
|
||||||
|
.as_inner()
|
||||||
|
.iter()
|
||||||
|
.map(|(k, _)| k.as_inner())
|
||||||
|
.sorted()
|
||||||
|
.ne(formals.iter().map(|(k, _)| k).sorted())
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
for (formal, default) in formals {
|
||||||
|
// let arg = if let Some(default) = default {
|
||||||
|
// arg.select(format)
|
||||||
|
// }
|
||||||
|
let arg = arg
|
||||||
|
.select(formal.clone().into())
|
||||||
|
.or_else(|| default.map(|idx| Value::Thunk(Thunk(idx))))
|
||||||
|
.unwrap();
|
||||||
|
new.insert_mut(formal.into(), arg);
|
||||||
|
}
|
||||||
|
if let Some(alias) = alias {
|
||||||
|
new.insert_mut(alias.into(), Value::AttrSet(arg));
|
||||||
|
}
|
||||||
|
env.enter(new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.eval(self.opcodes, &mut env).unwrap()
|
vm.eval(self.opcodes, &mut env).unwrap()
|
||||||
|
|||||||
@@ -173,4 +173,7 @@ fn test_func() {
|
|||||||
test_expr("(x: x) 1", int!(1));
|
test_expr("(x: x) 1", int!(1));
|
||||||
test_expr("(x: x) (x: x) 1", int!(1));
|
test_expr("(x: x) (x: x) 1", int!(1));
|
||||||
test_expr("(x: y: x + y) 1 1", int!(2));
|
test_expr("(x: y: x + y) 1 1", int!(2));
|
||||||
|
test_expr("({ x, y }: x + y) { x = 1; y = 2; }", int!(3));
|
||||||
|
test_expr("({ x, y, ... }: x + y) { x = 1; y = 2; z = 3; }", int!(3));
|
||||||
|
test_expr("(inputs@{ x, y, ... }: x + inputs.y) { x = 1; y = 2; z = 3; }", int!(3));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,9 +111,6 @@ impl VM {
|
|||||||
OpCode::SetAlias { sym } => {
|
OpCode::SetAlias { sym } => {
|
||||||
stack.tos_mut()?.as_mut().unwrap_func().set_alias(sym);
|
stack.tos_mut()?.as_mut().unwrap_func().set_alias(sym);
|
||||||
}
|
}
|
||||||
OpCode::Ret => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
OpCode::UnOp { op } => {
|
OpCode::UnOp { op } => {
|
||||||
use UnOp::*;
|
use UnOp::*;
|
||||||
let value = stack.pop()?;
|
let value = stack.pop()?;
|
||||||
@@ -200,7 +197,7 @@ impl VM {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
OpCode::EnterEnv => {
|
OpCode::EnterEnv => {
|
||||||
env.enter(stack.pop()?.unwrap_attr_set().to_data());
|
env.enter(stack.pop()?.unwrap_attr_set().into_inner());
|
||||||
}
|
}
|
||||||
OpCode::LeaveEnv => {
|
OpCode::LeaveEnv => {
|
||||||
env.leave();
|
env.leave();
|
||||||
|
|||||||
Reference in New Issue
Block a user