separate compiler & chunk
This commit is contained in:
parent
40d4f48878
commit
4fa2ce5e78
197
src/compiler.rs
197
src/compiler.rs
|
@ -80,14 +80,41 @@ pub struct Binding {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
|
pub constants: Vec<Value>,
|
||||||
|
pub bytecode: Vec<u8>,
|
||||||
|
pub strings: Vec<&'static str>,
|
||||||
|
pub keywords: Vec<&'static str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Chunk {
|
||||||
|
pub fn dissasemble_instr(&self, i: usize) {
|
||||||
|
let op = Op::from_u8(self.bytecode[i]).unwrap();
|
||||||
|
use Op::*;
|
||||||
|
match op {
|
||||||
|
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
||||||
|
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch => {
|
||||||
|
println!("{i:04}: {op}")
|
||||||
|
}
|
||||||
|
Constant | MatchConstant => {
|
||||||
|
let next = self.bytecode[i + 1];
|
||||||
|
let value = &self.constants[next as usize].show(self);
|
||||||
|
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
||||||
|
}
|
||||||
|
PushBinding | MatchTuple | PushTuple | PushDict | PushList | PushBox | Jump
|
||||||
|
| JumpIfFalse | JumpIfNoMatch => {
|
||||||
|
let next = self.bytecode[i + 1];
|
||||||
|
println!("{i:04}: {:16} {next:04}", op.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Compiler {
|
||||||
|
pub chunk: Chunk,
|
||||||
pub bindings: Vec<Binding>,
|
pub bindings: Vec<Binding>,
|
||||||
scope_depth: isize,
|
scope_depth: isize,
|
||||||
num_bindings: usize,
|
num_bindings: usize,
|
||||||
pub constants: Vec<Value>,
|
|
||||||
pub bytecode: Vec<u8>,
|
|
||||||
pub spans: Vec<SimpleSpan>,
|
pub spans: Vec<SimpleSpan>,
|
||||||
pub strings: Vec<&'static str>,
|
|
||||||
pub keywords: Vec<&'static str>,
|
|
||||||
pub nodes: Vec<&'static Ast>,
|
pub nodes: Vec<&'static Ast>,
|
||||||
pub ast: &'static Ast,
|
pub ast: &'static Ast,
|
||||||
pub span: SimpleSpan,
|
pub span: SimpleSpan,
|
||||||
|
@ -105,19 +132,22 @@ fn is_binding(expr: &Spanned<Ast>) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Compiler {
|
||||||
pub fn new(ast: &'static Spanned<Ast>, name: &'static str, src: &'static str) -> Chunk {
|
pub fn new(ast: &'static Spanned<Ast>, name: &'static str, src: &'static str) -> Compiler {
|
||||||
Chunk {
|
let chunk = Chunk {
|
||||||
bindings: vec![],
|
|
||||||
scope_depth: -1,
|
|
||||||
num_bindings: 0,
|
|
||||||
constants: vec![],
|
constants: vec![],
|
||||||
bytecode: vec![],
|
bytecode: vec![],
|
||||||
spans: vec![],
|
|
||||||
strings: vec![],
|
strings: vec![],
|
||||||
keywords: vec![
|
keywords: vec![
|
||||||
"nil", "bool", "number", "keyword", "string", "tuple", "list", "dict", "box", "fn",
|
"nil", "bool", "number", "keyword", "string", "tuple", "list", "dict", "box", "fn",
|
||||||
],
|
],
|
||||||
|
};
|
||||||
|
Compiler {
|
||||||
|
chunk,
|
||||||
|
bindings: vec![],
|
||||||
|
scope_depth: -1,
|
||||||
|
num_bindings: 0,
|
||||||
|
spans: vec![],
|
||||||
nodes: vec![],
|
nodes: vec![],
|
||||||
ast: &ast.0,
|
ast: &ast.0,
|
||||||
span: ast.1,
|
span: ast.1,
|
||||||
|
@ -131,7 +161,7 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kw_index_from(&self, kw: &str) -> Option<usize> {
|
pub fn kw_index_from(&self, kw: &str) -> Option<usize> {
|
||||||
self.keywords.iter().position(|s| *s == kw)
|
self.chunk.keywords.iter().position(|s| *s == kw)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn visit(&mut self, node: &'static Spanned<Ast>) {
|
pub fn visit(&mut self, node: &'static Spanned<Ast>) {
|
||||||
|
@ -146,24 +176,24 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_constant(&mut self, val: Value) {
|
fn emit_constant(&mut self, val: Value) {
|
||||||
let constant_index = self.constants.len();
|
let constant_index = self.chunk.constants.len();
|
||||||
if constant_index > u8::MAX as usize {
|
if constant_index > u8::MAX as usize {
|
||||||
panic!(
|
panic!(
|
||||||
"internal Ludus compiler error: too many constants in chunk:{}:: {}",
|
"internal Ludus compiler error: too many constants in chunk:{}:: {}",
|
||||||
self.span, self.ast
|
self.span, self.ast
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
self.constants.push(val);
|
self.chunk.constants.push(val);
|
||||||
self.bytecode.push(Op::Constant as u8);
|
self.chunk.bytecode.push(Op::Constant as u8);
|
||||||
self.spans.push(self.span);
|
self.spans.push(self.span);
|
||||||
self.bytecode.push(constant_index as u8);
|
self.chunk.bytecode.push(constant_index as u8);
|
||||||
self.spans.push(self.span);
|
self.spans.push(self.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_constant(&mut self, val: Value) {
|
fn match_constant(&mut self, val: Value) {
|
||||||
let constant_index = match self.constants.iter().position(|v| *v == val) {
|
let constant_index = match self.chunk.constants.iter().position(|v| *v == val) {
|
||||||
Some(idx) => idx,
|
Some(idx) => idx,
|
||||||
None => self.constants.len(),
|
None => self.chunk.constants.len(),
|
||||||
};
|
};
|
||||||
if constant_index > u8::MAX as usize {
|
if constant_index > u8::MAX as usize {
|
||||||
panic!(
|
panic!(
|
||||||
|
@ -171,18 +201,18 @@ impl Chunk {
|
||||||
self.span, self.ast
|
self.span, self.ast
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if constant_index == self.constants.len() {
|
if constant_index == self.chunk.constants.len() {
|
||||||
self.constants.push(val);
|
self.chunk.constants.push(val);
|
||||||
}
|
}
|
||||||
self.bytecode.push(Op::MatchConstant as u8);
|
self.chunk.bytecode.push(Op::MatchConstant as u8);
|
||||||
self.spans.push(self.span);
|
self.spans.push(self.span);
|
||||||
self.bytecode.push(constant_index as u8);
|
self.chunk.bytecode.push(constant_index as u8);
|
||||||
self.spans.push(self.span);
|
self.spans.push(self.span);
|
||||||
self.bind("");
|
self.bind("");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_op(&mut self, op: Op) {
|
fn emit_op(&mut self, op: Op) {
|
||||||
self.bytecode.push(op as u8);
|
self.chunk.bytecode.push(op as u8);
|
||||||
self.spans.push(self.span);
|
self.spans.push(self.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,22 +230,22 @@ impl Chunk {
|
||||||
Number(n) => self.emit_constant(Value::Number(*n)),
|
Number(n) => self.emit_constant(Value::Number(*n)),
|
||||||
Boolean(b) => self.emit_op(if *b { Op::True } else { Op::False }),
|
Boolean(b) => self.emit_op(if *b { Op::True } else { Op::False }),
|
||||||
String(s) => {
|
String(s) => {
|
||||||
let existing_str = self.strings.iter().position(|e| e == s);
|
let existing_str = self.chunk.strings.iter().position(|e| e == s);
|
||||||
let str_index = match existing_str {
|
let str_index = match existing_str {
|
||||||
Some(idx) => idx,
|
Some(idx) => idx,
|
||||||
None => self.strings.len(),
|
None => self.chunk.strings.len(),
|
||||||
};
|
};
|
||||||
self.strings.push(s);
|
self.chunk.strings.push(s);
|
||||||
self.emit_constant(Value::Interned(str_index));
|
self.emit_constant(Value::Interned(str_index));
|
||||||
}
|
}
|
||||||
Keyword(s) => {
|
Keyword(s) => {
|
||||||
let existing_kw = self.keywords.iter().position(|kw| kw == s);
|
let existing_kw = self.chunk.keywords.iter().position(|kw| kw == s);
|
||||||
let kw_index = match existing_kw {
|
let kw_index = match existing_kw {
|
||||||
Some(index) => index,
|
Some(index) => index,
|
||||||
None => self.keywords.len(),
|
None => self.chunk.keywords.len(),
|
||||||
};
|
};
|
||||||
if kw_index == self.keywords.len() {
|
if kw_index == self.chunk.keywords.len() {
|
||||||
self.keywords.push(s);
|
self.chunk.keywords.push(s);
|
||||||
}
|
}
|
||||||
self.emit_constant(Value::Keyword(kw_index));
|
self.emit_constant(Value::Keyword(kw_index));
|
||||||
}
|
}
|
||||||
|
@ -244,19 +274,19 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
If(cond, then, r#else) => {
|
If(cond, then, r#else) => {
|
||||||
self.visit(cond);
|
self.visit(cond);
|
||||||
let jif_idx = self.bytecode.len();
|
let jif_idx = self.chunk.bytecode.len();
|
||||||
self.emit_op(Op::JumpIfFalse);
|
self.emit_op(Op::JumpIfFalse);
|
||||||
self.bytecode.push(0xff);
|
self.chunk.bytecode.push(0xff);
|
||||||
self.visit(then);
|
self.visit(then);
|
||||||
let jump_idx = self.bytecode.len();
|
let jump_idx = self.chunk.bytecode.len();
|
||||||
self.emit_op(Op::Jump);
|
self.emit_op(Op::Jump);
|
||||||
self.bytecode.push(0xff);
|
self.chunk.bytecode.push(0xff);
|
||||||
self.visit(r#else);
|
self.visit(r#else);
|
||||||
let end_idx = self.bytecode.len();
|
let end_idx = self.chunk.bytecode.len();
|
||||||
let jif_offset = jump_idx - jif_idx;
|
let jif_offset = jump_idx - jif_idx;
|
||||||
let jump_offset = end_idx - jump_idx;
|
let jump_offset = end_idx - jump_idx;
|
||||||
self.bytecode[jif_idx + 1] = jif_offset as u8;
|
self.chunk.bytecode[jif_idx + 1] = jif_offset as u8;
|
||||||
self.bytecode[jump_idx + 1] = jump_offset as u8;
|
self.chunk.bytecode[jump_idx + 1] = jump_offset as u8;
|
||||||
}
|
}
|
||||||
Let(patt, expr) => {
|
Let(patt, expr) => {
|
||||||
self.emit_op(Op::ResetMatch);
|
self.emit_op(Op::ResetMatch);
|
||||||
|
@ -273,7 +303,7 @@ impl Chunk {
|
||||||
let biter = self.bindings.iter().enumerate().rev();
|
let biter = self.bindings.iter().enumerate().rev();
|
||||||
for (i, binding) in biter {
|
for (i, binding) in biter {
|
||||||
if binding.name == *name {
|
if binding.name == *name {
|
||||||
self.bytecode.push(i as u8);
|
self.chunk.bytecode.push(i as u8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,24 +329,24 @@ impl Chunk {
|
||||||
self.match_constant(Value::Number(*n));
|
self.match_constant(Value::Number(*n));
|
||||||
}
|
}
|
||||||
KeywordPattern(s) => {
|
KeywordPattern(s) => {
|
||||||
let existing_kw = self.keywords.iter().position(|kw| kw == s);
|
let existing_kw = self.chunk.keywords.iter().position(|kw| kw == s);
|
||||||
let kw_index = match existing_kw {
|
let kw_index = match existing_kw {
|
||||||
Some(index) => index,
|
Some(index) => index,
|
||||||
None => self.keywords.len(),
|
None => self.chunk.keywords.len(),
|
||||||
};
|
};
|
||||||
if kw_index == self.keywords.len() {
|
if kw_index == self.chunk.keywords.len() {
|
||||||
self.keywords.push(s);
|
self.chunk.keywords.push(s);
|
||||||
}
|
}
|
||||||
self.match_constant(Value::Keyword(kw_index));
|
self.match_constant(Value::Keyword(kw_index));
|
||||||
}
|
}
|
||||||
StringPattern(s) => {
|
StringPattern(s) => {
|
||||||
let existing_str = self.strings.iter().position(|e| e == s);
|
let existing_str = self.chunk.strings.iter().position(|e| e == s);
|
||||||
let str_index = match existing_str {
|
let str_index = match existing_str {
|
||||||
Some(idx) => idx,
|
Some(idx) => idx,
|
||||||
None => self.strings.len(),
|
None => self.chunk.strings.len(),
|
||||||
};
|
};
|
||||||
if str_index == self.strings.len() {
|
if str_index == self.chunk.strings.len() {
|
||||||
self.strings.push(s)
|
self.chunk.strings.push(s)
|
||||||
}
|
}
|
||||||
self.match_constant(Value::Interned(str_index));
|
self.match_constant(Value::Interned(str_index));
|
||||||
}
|
}
|
||||||
|
@ -325,14 +355,14 @@ impl Chunk {
|
||||||
self.visit(member);
|
self.visit(member);
|
||||||
}
|
}
|
||||||
self.emit_op(Op::PushTuple);
|
self.emit_op(Op::PushTuple);
|
||||||
self.bytecode.push(members.len() as u8);
|
self.chunk.bytecode.push(members.len() as u8);
|
||||||
}
|
}
|
||||||
List(members) => {
|
List(members) => {
|
||||||
for member in members {
|
for member in members {
|
||||||
self.visit(member);
|
self.visit(member);
|
||||||
}
|
}
|
||||||
self.emit_op(Op::PushList);
|
self.emit_op(Op::PushList);
|
||||||
self.bytecode.push(members.len() as u8);
|
self.chunk.bytecode.push(members.len() as u8);
|
||||||
}
|
}
|
||||||
LBox(name, expr) => {
|
LBox(name, expr) => {
|
||||||
self.visit(expr);
|
self.visit(expr);
|
||||||
|
@ -344,16 +374,16 @@ impl Chunk {
|
||||||
self.visit(pair);
|
self.visit(pair);
|
||||||
}
|
}
|
||||||
self.emit_op(Op::PushDict);
|
self.emit_op(Op::PushDict);
|
||||||
self.bytecode.push(pairs.len() as u8);
|
self.chunk.bytecode.push(pairs.len() as u8);
|
||||||
}
|
}
|
||||||
Pair(key, value) => {
|
Pair(key, value) => {
|
||||||
let existing_kw = self.keywords.iter().position(|kw| kw == key);
|
let existing_kw = self.chunk.keywords.iter().position(|kw| kw == key);
|
||||||
let kw_index = match existing_kw {
|
let kw_index = match existing_kw {
|
||||||
Some(index) => index,
|
Some(index) => index,
|
||||||
None => self.keywords.len(),
|
None => self.chunk.keywords.len(),
|
||||||
};
|
};
|
||||||
if kw_index == self.keywords.len() {
|
if kw_index == self.chunk.keywords.len() {
|
||||||
self.keywords.push(key);
|
self.chunk.keywords.push(key);
|
||||||
}
|
}
|
||||||
self.emit_constant(Value::Keyword(kw_index));
|
self.emit_constant(Value::Keyword(kw_index));
|
||||||
self.visit(value);
|
self.visit(value);
|
||||||
|
@ -386,18 +416,18 @@ impl Chunk {
|
||||||
while let Some((WhenClause(cond, body), _)) = clauses.next() {
|
while let Some((WhenClause(cond, body), _)) = clauses.next() {
|
||||||
self.visit(cond.as_ref());
|
self.visit(cond.as_ref());
|
||||||
self.emit_op(Op::JumpIfFalse);
|
self.emit_op(Op::JumpIfFalse);
|
||||||
let jif_jump_idx = self.bytecode.len();
|
let jif_jump_idx = self.chunk.bytecode.len();
|
||||||
self.bytecode.push(0xff);
|
self.chunk.bytecode.push(0xff);
|
||||||
self.visit(body);
|
self.visit(body);
|
||||||
self.emit_op(Op::Jump);
|
self.emit_op(Op::Jump);
|
||||||
jump_idxes.push(self.bytecode.len());
|
jump_idxes.push(self.chunk.bytecode.len());
|
||||||
self.bytecode.push(0xff);
|
self.chunk.bytecode.push(0xff);
|
||||||
self.bytecode[jif_jump_idx] =
|
self.chunk.bytecode[jif_jump_idx] =
|
||||||
self.bytecode.len() as u8 - jif_jump_idx as u8 - 1;
|
self.chunk.bytecode.len() as u8 - jif_jump_idx as u8 - 1;
|
||||||
}
|
}
|
||||||
self.emit_op(Op::PanicNoWhen);
|
self.emit_op(Op::PanicNoWhen);
|
||||||
for idx in jump_idxes {
|
for idx in jump_idxes {
|
||||||
self.bytecode[idx] = self.bytecode.len() as u8 - idx as u8 + 1;
|
self.chunk.bytecode[idx] = self.chunk.bytecode.len() as u8 - idx as u8 + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Match(scrutinee, clauses) => {
|
Match(scrutinee, clauses) => {
|
||||||
|
@ -409,8 +439,8 @@ impl Chunk {
|
||||||
self.scope_depth += 1;
|
self.scope_depth += 1;
|
||||||
self.visit(pattern);
|
self.visit(pattern);
|
||||||
self.emit_op(Op::JumpIfNoMatch);
|
self.emit_op(Op::JumpIfNoMatch);
|
||||||
let jnm_jump_idx = self.bytecode.len();
|
let jnm_jump_idx = self.chunk.bytecode.len();
|
||||||
self.bytecode.push(0xff);
|
self.chunk.bytecode.push(0xff);
|
||||||
self.visit(body);
|
self.visit(body);
|
||||||
self.emit_op(Op::Store);
|
self.emit_op(Op::Store);
|
||||||
self.scope_depth -= 1;
|
self.scope_depth -= 1;
|
||||||
|
@ -423,15 +453,15 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.emit_op(Op::Jump);
|
self.emit_op(Op::Jump);
|
||||||
jump_idxes.push(self.bytecode.len());
|
jump_idxes.push(self.chunk.bytecode.len());
|
||||||
self.bytecode.push(0xff);
|
self.chunk.bytecode.push(0xff);
|
||||||
self.bytecode[jnm_jump_idx] =
|
self.chunk.bytecode[jnm_jump_idx] =
|
||||||
self.bytecode.len() as u8 - jnm_jump_idx as u8 - 1;
|
self.chunk.bytecode.len() as u8 - jnm_jump_idx as u8 - 1;
|
||||||
}
|
}
|
||||||
self.emit_op(Op::PanicNoMatch);
|
self.emit_op(Op::PanicNoMatch);
|
||||||
self.emit_op(Op::Load);
|
self.emit_op(Op::Load);
|
||||||
for idx in jump_idxes {
|
for idx in jump_idxes {
|
||||||
self.bytecode[idx] = self.bytecode.len() as u8 - idx as u8 + 2;
|
self.chunk.bytecode[idx] = self.chunk.bytecode.len() as u8 - idx as u8 + 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Fn(name, body, doc) => {
|
Fn(name, body, doc) => {
|
||||||
|
@ -442,17 +472,17 @@ impl Chunk {
|
||||||
self.bind(name);
|
self.bind(name);
|
||||||
|
|
||||||
// compile the function
|
// compile the function
|
||||||
let mut chunk = Chunk::new(body, self.name, self.src);
|
let mut compiler = Compiler::new(body, self.name, self.src);
|
||||||
chunk.compile();
|
compiler.compile();
|
||||||
if crate::DEBUG_COMPILE {
|
if crate::DEBUG_COMPILE {
|
||||||
println!("==function: {name}==");
|
println!("==function: {name}==");
|
||||||
chunk.disassemble();
|
compiler.disassemble();
|
||||||
}
|
}
|
||||||
|
|
||||||
let lfn = crate::value::LFn {
|
let lfn = crate::value::LFn {
|
||||||
name,
|
name,
|
||||||
doc: *doc,
|
doc: *doc,
|
||||||
chunk,
|
chunk: compiler.chunk,
|
||||||
closed: vec![],
|
closed: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -475,7 +505,7 @@ impl Chunk {
|
||||||
pub fn disassemble(&self) {
|
pub fn disassemble(&self) {
|
||||||
println!("=== chunk: {} ===", self.name);
|
println!("=== chunk: {} ===", self.name);
|
||||||
println!("IDX | CODE | INFO");
|
println!("IDX | CODE | INFO");
|
||||||
let mut codes = self.bytecode.iter().enumerate();
|
let mut codes = self.chunk.bytecode.iter().enumerate();
|
||||||
while let Some((i, byte)) = codes.next() {
|
while let Some((i, byte)) = codes.next() {
|
||||||
let op = Op::from_u8(*byte).unwrap();
|
let op = Op::from_u8(*byte).unwrap();
|
||||||
use Op::*;
|
use Op::*;
|
||||||
|
@ -486,7 +516,7 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
let (_, next) = codes.next().unwrap();
|
let (_, next) = codes.next().unwrap();
|
||||||
let value = &self.constants[*next as usize].show(self);
|
let value = &self.chunk.constants[*next as usize].show(&self.chunk);
|
||||||
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
||||||
}
|
}
|
||||||
PushBinding | MatchTuple | PushTuple | PushDict | PushList | PushBox | Jump
|
PushBinding | MatchTuple | PushTuple | PushDict | PushList | PushBox | Jump
|
||||||
|
@ -497,25 +527,4 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dissasemble_instr(&self, i: usize) {
|
|
||||||
let op = Op::from_u8(self.bytecode[i]).unwrap();
|
|
||||||
use Op::*;
|
|
||||||
match op {
|
|
||||||
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
|
||||||
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch => {
|
|
||||||
println!("{i:04}: {op}")
|
|
||||||
}
|
|
||||||
Constant | MatchConstant => {
|
|
||||||
let next = self.bytecode[i + 1];
|
|
||||||
let value = &self.constants[next as usize].show(self);
|
|
||||||
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
|
||||||
}
|
|
||||||
PushBinding | MatchTuple | PushTuple | PushDict | PushList | PushBox | Jump
|
|
||||||
| JumpIfFalse | JumpIfNoMatch => {
|
|
||||||
let next = self.bytecode[i + 1];
|
|
||||||
println!("{i:04}: {:16} {next:04}", op.to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -17,7 +17,7 @@ use crate::parser::{parser, Ast};
|
||||||
mod validator;
|
mod validator;
|
||||||
|
|
||||||
mod compiler;
|
mod compiler;
|
||||||
use crate::compiler::Chunk;
|
use crate::compiler::Compiler;
|
||||||
|
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
|
@ -46,10 +46,10 @@ pub fn run(src: &'static str) {
|
||||||
// in any event, the AST should live forever
|
// in any event, the AST should live forever
|
||||||
let parsed: &'static Spanned<Ast> = Box::leak(Box::new(parse_result.unwrap()));
|
let parsed: &'static Spanned<Ast> = Box::leak(Box::new(parse_result.unwrap()));
|
||||||
|
|
||||||
let mut chunk = Chunk::new(parsed, "test", src);
|
let mut compiler = Compiler::new(parsed, "test", src);
|
||||||
chunk.compile();
|
compiler.compile();
|
||||||
if DEBUG_COMPILE {
|
if DEBUG_COMPILE {
|
||||||
chunk.disassemble();
|
compiler.disassemble();
|
||||||
println!("\n\n")
|
println!("\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,10 +57,10 @@ pub fn run(src: &'static str) {
|
||||||
println!("=== vm run: test ===");
|
println!("=== vm run: test ===");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut vm = Vm::new(&chunk);
|
let mut vm = Vm::new(&compiler.chunk);
|
||||||
let result = vm.interpret();
|
let result = vm.interpret();
|
||||||
let output = match result {
|
let output = match result {
|
||||||
Ok(val) => val.show(&chunk),
|
Ok(val) => val.show(&compiler.chunk),
|
||||||
Err(panic) => format!("{:?}", panic),
|
Err(panic) => format!("{:?}", panic),
|
||||||
};
|
};
|
||||||
println!("{output}");
|
println!("{output}");
|
||||||
|
|
|
@ -78,7 +78,7 @@ impl std::fmt::Display for Value {
|
||||||
.join(", ")
|
.join(", ")
|
||||||
),
|
),
|
||||||
Box(value) => write!(f, "box {}", value.as_ref().borrow()),
|
Box(value) => write!(f, "box {}", value.as_ref().borrow()),
|
||||||
Fn(lfn) => write!(f, "fn {}", lfn.name),
|
Fn(lfn) => write!(f, "fn {}", lfn.get().unwrap().name),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ impl Value {
|
||||||
}
|
}
|
||||||
String(s) => s.as_ref().clone(),
|
String(s) => s.as_ref().clone(),
|
||||||
Box(x) => format!("box {{ {} }}", x.as_ref().borrow().show(ctx)),
|
Box(x) => format!("box {{ {} }}", x.as_ref().borrow().show(ctx)),
|
||||||
Fn(lfn) => format!("fn {}", lfn.name),
|
Fn(lfn) => format!("fn {}", lfn.get().unwrap().name),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user