method syntax sugar achieved
This commit is contained in:
parent
12389ae371
commit
0cd682de21
|
@ -425,7 +425,7 @@ function __wbg_get_imports() {
|
|||
_assertBoolean(ret);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper7701 = function() { return logError(function (arg0, arg1, arg2) {
|
||||
imports.wbg.__wbindgen_closure_wrapper7779 = function() { return logError(function (arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 347, __wbg_adapter_22);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
|
|
Binary file not shown.
|
@ -34,6 +34,7 @@ pub enum Ast {
|
|||
Boolean(bool),
|
||||
Number(f64),
|
||||
Keyword(&'static str),
|
||||
Method(&'static str, Box<Spanned<Self>>),
|
||||
Word(&'static str),
|
||||
String(&'static str),
|
||||
Interpolated(Vec<Spanned<StringPart>>),
|
||||
|
@ -103,6 +104,7 @@ impl Ast {
|
|||
Boolean(b) | BooleanPattern(b) => b.to_string(),
|
||||
Number(n) | NumberPattern(n) => n.to_string(),
|
||||
Keyword(k) | KeywordPattern(k) => format!(":{k}"),
|
||||
Method(m, args) => format!("::{m} {}", args.0),
|
||||
Word(w) | WordPattern(w) => w.to_string(),
|
||||
Block(lines) => {
|
||||
let mut out = "{\n".to_string();
|
||||
|
@ -260,6 +262,7 @@ impl fmt::Display for Ast {
|
|||
Boolean(b) => write!(f, "Boolean: {}", b),
|
||||
Number(n) => write!(f, "Number: {}", n),
|
||||
Keyword(k) => write!(f, "Keyword: :{}", k),
|
||||
Method(m, args) => write!(f, "Method: ::{m} ({})", args.0),
|
||||
Word(w) => write!(f, "Word: {}", w),
|
||||
Block(b) => write!(
|
||||
f,
|
||||
|
|
|
@ -37,7 +37,8 @@ impl Chunk {
|
|||
| Mult | Div | Unbox | BoxStore | Assert | Get | At | Not | Panic | EmptyString
|
||||
| ConcatStrings | Stringify | MatchType | Return | UnconditionalMatch | Print
|
||||
| AppendList | ConcatList | PushList | PushDict | AppendDict | ConcatDict | Nothing
|
||||
| PushGlobal | SetUpvalue | LoadMessage | NextMessage | MatchMessage | ClearMessage => {
|
||||
| PushGlobal | SetUpvalue | LoadMessage | NextMessage | MatchMessage | ClearMessage
|
||||
| SendMethod => {
|
||||
println!("{i:04}: {op}")
|
||||
}
|
||||
Constant | MatchConstant => {
|
||||
|
|
|
@ -860,6 +860,14 @@ impl Compiler {
|
|||
self.stack_depth -= 1;
|
||||
self.report_depth("after keyword access");
|
||||
}
|
||||
(Keyword(_), Method(str, args)) | (Word(_), Method(str, args)) => {
|
||||
self.visit(first);
|
||||
self.emit_constant(Value::Keyword(str));
|
||||
self.visit(args);
|
||||
self.emit_op(Op::SendMethod);
|
||||
// target, method, args -> result
|
||||
self.stack_depth -= 2;
|
||||
}
|
||||
(Keyword(_), Arguments(args)) => {
|
||||
self.visit(&args[0]);
|
||||
self.visit(first);
|
||||
|
@ -954,8 +962,16 @@ impl Compiler {
|
|||
Keyword(str) => {
|
||||
self.emit_constant(Value::Keyword(str));
|
||||
self.emit_op(Op::GetKey);
|
||||
// target, keyword -> value
|
||||
self.stack_depth -= 1;
|
||||
}
|
||||
Method(str, args) => {
|
||||
self.emit_constant(Value::Keyword(str));
|
||||
self.visit(args);
|
||||
self.emit_op(Op::SendMethod);
|
||||
// target, method, args -> result
|
||||
self.stack_depth -= 2;
|
||||
}
|
||||
Arguments(args) => {
|
||||
self.store();
|
||||
let arity = args.len();
|
||||
|
@ -1475,7 +1491,7 @@ impl Compiler {
|
|||
Placeholder => {
|
||||
self.emit_op(Op::Nothing);
|
||||
}
|
||||
And | Or | Arguments(..) => unreachable!(),
|
||||
And | Or | Arguments(..) | Method(..) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ pub enum Token {
|
|||
// todo: hard code these types
|
||||
Reserved(&'static str),
|
||||
Punctuation(&'static str),
|
||||
Method(&'static str),
|
||||
}
|
||||
|
||||
impl fmt::Display for Token {
|
||||
|
@ -26,6 +27,7 @@ impl fmt::Display for Token {
|
|||
Token::Reserved(r) => write!(f, "[Reserved {}]", r),
|
||||
Token::Nil => write!(f, "[nil]"),
|
||||
Token::Punctuation(p) => write!(f, "[Punctuation {}]", p),
|
||||
Token::Method(m) => write!(f, "[Method {m}]"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +64,8 @@ pub fn lexer(
|
|||
_ => Token::Word(word),
|
||||
});
|
||||
|
||||
let method = just("::").ignore_then(word).map(Token::Method);
|
||||
|
||||
let keyword = just(':').ignore_then(word).map(Token::Keyword);
|
||||
|
||||
let string = just('"')
|
||||
|
@ -81,6 +85,7 @@ pub fn lexer(
|
|||
let token = number
|
||||
.or(reserved_or_word)
|
||||
.or(keyword)
|
||||
.or(method)
|
||||
.or(string)
|
||||
.or(punctuation);
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ pub enum Op {
|
|||
NextMessage,
|
||||
MatchMessage,
|
||||
ClearMessage,
|
||||
SendMethod,
|
||||
// Inc,
|
||||
// Dec,
|
||||
// Gt,
|
||||
|
@ -230,6 +231,7 @@ impl std::fmt::Display for Op {
|
|||
NextMessage => "next_message",
|
||||
MatchMessage => "match_message",
|
||||
ClearMessage => "clear_message",
|
||||
SendMethod => "send_method",
|
||||
};
|
||||
write!(f, "{rep}")
|
||||
}
|
||||
|
|
|
@ -233,7 +233,7 @@ where
|
|||
)
|
||||
.map_with(|dict, e| (DictPattern(dict), e.span()));
|
||||
|
||||
let keyword = select! {Token::Keyword(k) => Keyword(k),}.map_with(|k, e| (k, e.span()));
|
||||
let keyword = select! {Token::Keyword(k) => Keyword(k)}.map_with(|k, e| (k, e.span()));
|
||||
|
||||
let as_pattern = select! {Token::Word(w) => w}
|
||||
.then_ignore(just(Token::Reserved("as")))
|
||||
|
@ -300,9 +300,13 @@ where
|
|||
|
||||
let and = just(Token::Reserved("and")).map_with(|_, e| (And, e.span()));
|
||||
|
||||
let method = select!(Token::Method(m) => m)
|
||||
.then(tuple.clone())
|
||||
.map_with(|(m, t), e| (Ast::Method(m, Box::new(t)), e.span()));
|
||||
|
||||
let synth_root = or.or(and).or(word).or(keyword);
|
||||
|
||||
let synth_term = keyword.or(args);
|
||||
let synth_term = keyword.or(args).or(method);
|
||||
|
||||
let synthetic = synth_root
|
||||
.then(synth_term.clone())
|
||||
|
|
|
@ -284,6 +284,13 @@ impl<'a> Validator<'a> {
|
|||
// check arity against fn info if first term is word and second term is args
|
||||
Synthetic(first, second, rest) => {
|
||||
match (&first.0, &second.0) {
|
||||
(Ast::Word(_), Ast::Method(_, args)) => {
|
||||
self.visit(first.as_ref());
|
||||
self.visit(args);
|
||||
}
|
||||
(Ast::Keyword(_), Ast::Method(_, args)) => {
|
||||
self.visit(args);
|
||||
}
|
||||
(Ast::And, Ast::Arguments(_)) | (Ast::Or, Ast::Arguments(_)) => {
|
||||
self.visit(second.as_ref())
|
||||
}
|
||||
|
@ -587,7 +594,7 @@ impl<'a> Validator<'a> {
|
|||
}
|
||||
PairPattern(_, patt) => self.visit(patt.as_ref()),
|
||||
// terminals can never be invalid
|
||||
Nil | Boolean(_) | Number(_) | Keyword(_) | String(_) | And | Or => (),
|
||||
Nil | Boolean(_) | Number(_) | Keyword(_) | String(_) | And | Or | Method(..) => (),
|
||||
// terminal patterns can never be invalid
|
||||
NilPattern | BooleanPattern(..) | NumberPattern(..) | StringPattern(..)
|
||||
| KeywordPattern(..) | PlaceholderPattern => (),
|
||||
|
|
77
src/vm.rs
77
src/vm.rs
|
@ -234,12 +234,14 @@ impl Creature {
|
|||
let msg = format!("{msg}\nPanic traceback:\n{}", self.call_stack());
|
||||
println!("process {} panicked!\n{msg}", self.pid);
|
||||
self.result = Some(Err(Panic::String(msg)));
|
||||
self.r#yield = true;
|
||||
}
|
||||
|
||||
pub fn panic_with(&mut self, msg: String) {
|
||||
let msg = format!("{msg}\nPanic traceback:\n{}", self.call_stack());
|
||||
println!("process {} panicked!\n{msg}", self.pid);
|
||||
self.result = Some(Err(Panic::String(msg)));
|
||||
self.r#yield = true;
|
||||
}
|
||||
|
||||
fn get_value_at(&mut self, idx: u8) -> Value {
|
||||
|
@ -269,6 +271,18 @@ impl Creature {
|
|||
self.ip >= self.chunk().bytecode.len()
|
||||
}
|
||||
|
||||
fn send_msg(&mut self, pid: Value, msg: Value) {
|
||||
let Value::Keyword(pid) = pid else {
|
||||
return self.panic_with(format!("Ludus expected pid keyword, and instead got {pid}"));
|
||||
};
|
||||
if self.pid == pid {
|
||||
self.mbx.push_back(msg.clone());
|
||||
} else {
|
||||
self.zoo.as_ref().borrow_mut().send_msg(pid, msg);
|
||||
}
|
||||
self.push(Value::Keyword("ok"));
|
||||
}
|
||||
|
||||
fn handle_msg(&mut self, args: Vec<Value>) {
|
||||
println!("message received by {}: {}", self.pid, args[0]);
|
||||
let Value::Keyword(msg) = args.first().unwrap() else {
|
||||
|
@ -277,24 +291,25 @@ impl Creature {
|
|||
match *msg {
|
||||
"self" => self.push(Value::Keyword(self.pid)),
|
||||
"send" => {
|
||||
let Value::Keyword(pid) = args[1] else {
|
||||
return self.panic("malformed pid");
|
||||
};
|
||||
println!(
|
||||
"sending msg from {} to {} of {}",
|
||||
self.pid,
|
||||
pid,
|
||||
args[2].show()
|
||||
);
|
||||
if self.pid == pid {
|
||||
self.mbx.push_back(args[2].clone());
|
||||
} else {
|
||||
self.zoo
|
||||
.as_ref()
|
||||
.borrow_mut()
|
||||
.send_msg(pid, args[2].clone());
|
||||
}
|
||||
self.push(Value::Keyword("ok"));
|
||||
self.send_msg(args[1].clone(), args[2].clone())
|
||||
// let Value::Keyword(pid) = args[1] else {
|
||||
// return self.panic("malformed pid");
|
||||
// };
|
||||
// println!(
|
||||
// "sending msg from {} to {} of {}",
|
||||
// self.pid,
|
||||
// pid,
|
||||
// args[2].show()
|
||||
// );
|
||||
// if self.pid == pid {
|
||||
// self.mbx.push_back(args[2].clone());
|
||||
// } else {
|
||||
// self.zoo
|
||||
// .as_ref()
|
||||
// .borrow_mut()
|
||||
// .send_msg(pid, args[2].clone());
|
||||
// }
|
||||
// self.push(Value::Keyword("ok"));
|
||||
}
|
||||
"spawn" => {
|
||||
let f = args[1].clone();
|
||||
|
@ -376,19 +391,19 @@ impl Creature {
|
|||
loop {
|
||||
if self.at_end() {
|
||||
let result = self.stack.pop().unwrap();
|
||||
println!("process {} has returned {result}", self.pid);
|
||||
// println!("process {} has returned {result}", self.pid);
|
||||
self.result = Some(Ok(result));
|
||||
return;
|
||||
}
|
||||
if self.r#yield {
|
||||
println!("process {} has explicitly yielded", self.pid);
|
||||
// println!("process {} has explicitly yielded", self.pid);
|
||||
return;
|
||||
}
|
||||
if self.reductions >= MAX_REDUCTIONS {
|
||||
println!(
|
||||
"process {} is yielding after {MAX_REDUCTIONS} reductions",
|
||||
self.pid
|
||||
);
|
||||
// println!(
|
||||
// "process {} is yielding after {MAX_REDUCTIONS} reductions",
|
||||
// self.pid
|
||||
// );
|
||||
return;
|
||||
}
|
||||
let code = self.read();
|
||||
|
@ -1231,11 +1246,23 @@ impl Creature {
|
|||
}
|
||||
},
|
||||
MatchMessage => {
|
||||
let matched = self.mbx.remove(self.msg_idx).unwrap();
|
||||
self.mbx.remove(self.msg_idx).unwrap();
|
||||
}
|
||||
ClearMessage => {
|
||||
self.msg_idx = 0;
|
||||
}
|
||||
SendMethod => {
|
||||
let Value::Tuple(args) = self.pop() else {
|
||||
unreachable!("method args should be a tuple");
|
||||
};
|
||||
let method = self.pop();
|
||||
let target = self.pop();
|
||||
let mut msg = vec![method];
|
||||
for arg in args.as_ref() {
|
||||
msg.push(arg.clone());
|
||||
}
|
||||
self.send_msg(target, Value::tuple(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user