added operator typehinting
This commit is contained in:
parent
ee1418c673
commit
edcfbea81d
|
@ -8,6 +8,6 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = "*"
|
regex = "*"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
rand = "0.8.5"
|
rand = "*"
|
||||||
colored = "*"
|
colored = "*"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
0xc8c7a99bb88e156b:
|
||||||
|
push int 0x2
|
||||||
|
push int 0x4
|
||||||
|
cmp eq int
|
||||||
|
jump-unless 0x6
|
||||||
|
push int 0x1
|
||||||
|
ret
|
||||||
|
push int 0x0
|
||||||
|
ret
|
|
@ -1,31 +1,40 @@
|
||||||
use crate::parser::data::Diagnostics;
|
use crate::parser::data::Diagnostics;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
gen_erpn: bool
|
gen_erpn: bool,
|
||||||
|
gen_vsasm: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
fn new() -> Self {
|
|
||||||
Settings {
|
|
||||||
gen_erpn: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gen_erpn(&self) -> bool {
|
pub fn gen_erpn(&self) -> bool {
|
||||||
self.gen_erpn
|
self.gen_erpn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn gen_vsasm(&self) -> bool {
|
||||||
|
self.gen_vsasm
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_args(diagnostics: &mut Diagnostics) -> Settings {
|
pub fn parse_args(diagnostics: &mut Diagnostics) -> Settings {
|
||||||
let args = std::env::args().collect::<Vec<String>>();
|
let args = std::env::args().collect::<Vec<String>>();
|
||||||
|
|
||||||
let mut settings = Settings::new();
|
let mut settings = Settings::default();
|
||||||
|
|
||||||
for arg in args.iter() {
|
for arg in args.iter() {
|
||||||
match arg.as_str() {
|
match arg.as_str() {
|
||||||
"--no-info" => diagnostics.set_loglvl(crate::parser::data::LogLvl::Warn),
|
"--no-info" => diagnostics.set_loglvl(crate::parser::data::LogLvl::Warn),
|
||||||
"--no-warn" => diagnostics.set_loglvl(crate::parser::data::LogLvl::Err),
|
"--no-warn" => diagnostics.set_loglvl(crate::parser::data::LogLvl::Err),
|
||||||
"--erpn" => settings.gen_erpn = true,
|
"--erpn" => settings.gen_erpn = true,
|
||||||
|
"--vsasm" => settings.gen_vsasm = true,
|
||||||
|
"-h" => println!(concat!(
|
||||||
|
"help:\n",
|
||||||
|
"--no-info: print only warning and errors\n",
|
||||||
|
"--no-warn: print only errors\n",
|
||||||
|
"--erpn: write a *.erpn (extended reverse polish notation) summary to disk\n",
|
||||||
|
"--vsasm: write a .vsasm (virtual simplified assembly language) summary to disk\n",
|
||||||
|
"-h: print this dialog"
|
||||||
|
)),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,5 +35,6 @@ pub fn convert_to_erpn<'a>(funcs: &mut Vec<Func<'a>>, declrs: &Vec<Declr<'a>>) {
|
||||||
|
|
||||||
// write down function body
|
// write down function body
|
||||||
write_expr(&mut file, &mut indent, func.expr.as_ref().unwrap());
|
write_expr(&mut file, &mut indent, func.expr.as_ref().unwrap());
|
||||||
|
writeln!(&mut file).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
14
src/main.rs
14
src/main.rs
|
@ -18,20 +18,20 @@ pub fn message<S>(typ: MessageType, msg: S)
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
println!("{}: {}", typ.to_colored(), msg.into().bold().bright_white());
|
println!("{}: {}\n", typ.to_colored(), msg.into().bold().bright_white());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let source = r"
|
let source = r"
|
||||||
|
-- structs are tables
|
||||||
foo(x:int) = int {
|
|
||||||
x / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
main() = int {
|
main() = int {
|
||||||
a = foo(4)
|
|
||||||
|
|
||||||
a
|
unless 2 == 4 {
|
||||||
|
yield 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield 0;
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
||||||
|
|
|
@ -324,6 +324,7 @@ fn discover_exprs<'a>(
|
||||||
}
|
}
|
||||||
expr = VecDeque::new();
|
expr = VecDeque::new();
|
||||||
blocks.push(Block::new());
|
blocks.push(Block::new());
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
'}' => {
|
'}' => {
|
||||||
|
@ -346,7 +347,7 @@ fn discover_exprs<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -613,7 +614,13 @@ fn parse_term<'a>(
|
||||||
Token::Assign(_, _, _) => {
|
Token::Assign(_, _, _) => {
|
||||||
op_stack.push(token);
|
op_stack.push(token);
|
||||||
}
|
}
|
||||||
Token::Keyword(_, _) => op_stack.push(token),
|
Token::Keyword(key, _) => {
|
||||||
|
match key {
|
||||||
|
Keyword::Unless => (),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
op_stack.push(token)
|
||||||
|
},
|
||||||
|
|
||||||
Token::Delemiter(char, _) => match char {
|
Token::Delemiter(char, _) => match char {
|
||||||
'(' => op_stack.push(token),
|
'(' => op_stack.push(token),
|
||||||
|
@ -689,6 +696,7 @@ fn parse_term<'a>(
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(mut token) = op_stack.pop() {
|
while let Some(mut token) = op_stack.pop() {
|
||||||
|
|
|
@ -161,12 +161,11 @@ impl Operator {
|
||||||
diagnostics: &mut crate::parser::data::Diagnostics,
|
diagnostics: &mut crate::parser::data::Diagnostics,
|
||||||
) -> Result<(Option<Prim>, Option<Prim>),()> {
|
) -> Result<(Option<Prim>, Option<Prim>),()> {
|
||||||
for combination in types.iter() {
|
for combination in types.iter() {
|
||||||
if let (result, hint) =
|
let (result, hint) =
|
||||||
self.present_types(operands, combination.0, combination.1, dbginf, diagnostics)?
|
self.present_types(operands, combination.0, combination.1, dbginf, diagnostics)?;
|
||||||
{
|
|
||||||
return Ok((result, hint));
|
return Ok((result, hint));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok((None, None))
|
Ok((None, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +499,7 @@ pub enum Token<'a> {
|
||||||
Keyword(Keyword, DebugInfo),
|
Keyword(Keyword, DebugInfo),
|
||||||
Type(Prim, DebugInfo),
|
Type(Prim, DebugInfo),
|
||||||
/// Semicolon
|
/// Semicolon
|
||||||
Terminator(DebugInfo),
|
Terminator(DebugInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for Token<'a> {
|
impl<'a> std::fmt::Display for Token<'a> {
|
||||||
|
|
141
src/vmrt/mod.rs
141
src/vmrt/mod.rs
|
@ -12,7 +12,17 @@ enum Data {
|
||||||
Int(i64),
|
Int(i64),
|
||||||
Rat(f64),
|
Rat(f64),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Off(u64),
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Data {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Data::Int(v) => f.write_fmt(format_args!("int {:#x}", v))?,
|
||||||
|
Data::Rat(v) => f.write_fmt(format_args!("float {}", v))?,
|
||||||
|
Data::Bool(v) => f.write_fmt(format_args!("bool {}", v))?
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
|
@ -95,7 +105,7 @@ enum Instr {
|
||||||
/// push the value stored at offset from the local stack onto the local stack
|
/// push the value stored at offset from the local stack onto the local stack
|
||||||
Load(usize),
|
Load(usize),
|
||||||
/// store the value stored at the stack[0](offset) stack[1](value) onto the stack
|
/// store the value stored at the stack[0](offset) stack[1](value) onto the stack
|
||||||
Store,
|
Store(usize),
|
||||||
|
|
||||||
Call(u64),
|
Call(u64),
|
||||||
|
|
||||||
|
@ -103,9 +113,67 @@ enum Instr {
|
||||||
|
|
||||||
Operation(Operation),
|
Operation(Operation),
|
||||||
|
|
||||||
|
Jump(usize),
|
||||||
|
JumpUnless(usize),
|
||||||
|
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Instr {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Instr::Pop => f.write_str("\tpop")?,
|
||||||
|
Instr::Exit => f.write_str("\texit")?,
|
||||||
|
Instr::Return => f.write_str("\tret")?,
|
||||||
|
Instr::Load(offset) => f.write_fmt(format_args!("\tload {:#x}", offset))?,
|
||||||
|
Instr::Push(value) => f.write_fmt(format_args!("\tpush {}", value))?,
|
||||||
|
Instr::Call(uuid) => f.write_fmt(format_args!("\tcall {:#x}", uuid))?,
|
||||||
|
Instr::Jump(offset) => f.write_fmt(format_args!("\tjump {:#x}", offset))?,
|
||||||
|
Instr::JumpUnless(offset) => f.write_fmt(format_args!("\tjump-unless {:#x}", offset))?,
|
||||||
|
Instr::Operation(op) => {
|
||||||
|
match op {
|
||||||
|
Operation::Int(op) => match op {
|
||||||
|
IntOp::Add => f.write_str("\tadd int")?,
|
||||||
|
IntOp::Sub => f.write_str("\tsub int")?,
|
||||||
|
IntOp::Mul => f.write_str("\tmul int")?,
|
||||||
|
IntOp::Div => f.write_str("\tdiv int")?,
|
||||||
|
|
||||||
|
IntOp::CmpEq => f.write_str("\tcmp eq int")?,
|
||||||
|
IntOp::CmpNEq => f.write_str("\tcmp not-eq int")?,
|
||||||
|
IntOp::CmpLt => f.write_str("\tcmp lt eq int")?,
|
||||||
|
IntOp::CmpGt => f.write_str("\tcmp gt int")?,
|
||||||
|
IntOp::CmpLtEq => f.write_str("\tcmp lt-eq int")?,
|
||||||
|
IntOp::CmpGtEq => f.write_str("\tcmp gt-eq int")?,
|
||||||
|
},
|
||||||
|
Operation::Rat(op) => match op {
|
||||||
|
RatOp::Add => f.write_str("\tadd float")?,
|
||||||
|
RatOp::Sub => f.write_str("\tsub float")?,
|
||||||
|
RatOp::Mul => f.write_str("\tmul float")?,
|
||||||
|
RatOp::Div => f.write_str("\tdiv float")?,
|
||||||
|
|
||||||
|
RatOp::CmpEq => f.write_str("\tcmp eq float")?,
|
||||||
|
RatOp::CmpNEq => f.write_str("\tcmp not-eq float")?,
|
||||||
|
RatOp::CmpLt => f.write_str("\tcmp lt eq float")?,
|
||||||
|
RatOp::CmpGt => f.write_str("\tcmp gt float")?,
|
||||||
|
RatOp::CmpLtEq => f.write_str("\tcmp lt-eq float")?,
|
||||||
|
RatOp::CmpGtEq => f.write_str("\tcmp gt-eq float")?,
|
||||||
|
},
|
||||||
|
Operation::Bool(op) => match op {
|
||||||
|
BoolOp::And => f.write_str("\tand")?,
|
||||||
|
BoolOp::Or => f.write_str("\tor")?,
|
||||||
|
BoolOp::Xor => f.write_str("\txor")?,
|
||||||
|
|
||||||
|
BoolOp::CmpNEq => f.write_str("\tcmp not-eq bool")?,
|
||||||
|
BoolOp::CmpEq => f.write_str("\tcmp eq bool")?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Instr::Store(offset) => f.write_fmt(format_args!("\tstore {:#x}", offset))?,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// function stack layout
|
/// function stack layout
|
||||||
/// +----------------------------------+
|
/// +----------------------------------+
|
||||||
/// | Parameter (0) |
|
/// | Parameter (0) |
|
||||||
|
@ -130,9 +198,16 @@ pub struct Program {
|
||||||
procs: HashMap<u64, Proc>,
|
procs: HashMap<u64, Proc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum LabelType {
|
||||||
|
Unless(usize),
|
||||||
|
Loop(usize),
|
||||||
|
Pad
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Compiletime<'a> {
|
struct Compiletime<'a> {
|
||||||
vartable: HashMap<&'a str, usize>,
|
vartable: HashMap<&'a str, usize>,
|
||||||
|
labels: Vec<LabelType>,
|
||||||
stacksize: usize,
|
stacksize: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,8 +218,9 @@ fn parse_term<'a>(
|
||||||
ct: &mut Compiletime<'a>,
|
ct: &mut Compiletime<'a>,
|
||||||
code: &mut Vec<Instr>,
|
code: &mut Vec<Instr>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
|
|
||||||
for token in term.iter() {
|
for token in term.iter() {
|
||||||
let instr = match token {
|
match token {
|
||||||
Token::Number(value, hint, _) => {
|
Token::Number(value, hint, _) => {
|
||||||
code.push(Instr::Push(match hint {
|
code.push(Instr::Push(match hint {
|
||||||
NumHint::Int => Data::Int(value.parse::<i64>().unwrap()),
|
NumHint::Int => Data::Int(value.parse::<i64>().unwrap()),
|
||||||
|
@ -158,12 +234,12 @@ fn parse_term<'a>(
|
||||||
}
|
}
|
||||||
Token::Arg(name, _) => {
|
Token::Arg(name, _) => {
|
||||||
let off = declr[x].get_arg_ord(name);
|
let off = declr[x].get_arg_ord(name);
|
||||||
|
|
||||||
code.push(Instr::Load(off));
|
code.push(Instr::Load(off));
|
||||||
ct.stacksize += 1;
|
ct.stacksize += 1;
|
||||||
}
|
}
|
||||||
Token::Assign(name, _, _) => {
|
Token::Assign(name, _, _) => {
|
||||||
ct.vartable.insert(name.clone(), ct.stacksize - 1);
|
ct.vartable.insert(name.clone(), ct.stacksize - 1);
|
||||||
|
code.push(Instr::Store(ct.stacksize - 1));
|
||||||
}
|
}
|
||||||
Token::Var(name, _) => {
|
Token::Var(name, _) => {
|
||||||
code.push(Instr::Load(*ct.vartable.get(name).unwrap()));
|
code.push(Instr::Load(*ct.vartable.get(name).unwrap()));
|
||||||
|
@ -254,10 +330,13 @@ fn parse_term<'a>(
|
||||||
Token::Keyword(keyword, _) => match keyword {
|
Token::Keyword(keyword, _) => match keyword {
|
||||||
crate::token::Keyword::Yield | crate::token::Keyword::Return => {
|
crate::token::Keyword::Yield | crate::token::Keyword::Return => {
|
||||||
code.push(Instr::Return)
|
code.push(Instr::Return)
|
||||||
|
},
|
||||||
|
crate::token::Keyword::Unless => {
|
||||||
|
ct.labels.push(LabelType::Unless(code.len()));
|
||||||
|
code.push(Instr::JumpUnless(0));
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -271,9 +350,24 @@ fn parse_block<'a>(
|
||||||
ct: &mut Compiletime<'a>,
|
ct: &mut Compiletime<'a>,
|
||||||
prog: &mut Vec<Instr>,
|
prog: &mut Vec<Instr>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
|
|
||||||
|
ct.labels.push(LabelType::Pad);
|
||||||
|
|
||||||
for expr in block.iter() {
|
for expr in block.iter() {
|
||||||
compile_expr(expr, x, declr, ct, prog)?;
|
compile_expr(expr, x, declr, ct, prog)?;
|
||||||
}
|
}
|
||||||
|
// resolve JumpUnless Labels
|
||||||
|
ct.labels.pop();
|
||||||
|
|
||||||
|
if let Some(label) = ct.labels.pop() {
|
||||||
|
match label {
|
||||||
|
LabelType::Unless(line) => {
|
||||||
|
prog[line] = Instr::JumpUnless(prog.len());
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +414,9 @@ pub fn compile<'a>(funcs: &Vec<Func<'a>>, declrs: &Vec<Declr<'a>>, settings: &cr
|
||||||
.insert(declrs[x].uuid(), create_proc(&declrs[x], code));
|
.insert(declrs[x].uuid(), create_proc(&declrs[x], code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if settings.gen_vsasm() {
|
||||||
|
output::dump_program(&prog);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(prog)
|
Ok(prog)
|
||||||
}
|
}
|
||||||
|
@ -345,6 +441,14 @@ impl Runtimestack {
|
||||||
pub fn peek(&mut self, index: usize) -> Data {
|
pub fn peek(&mut self, index: usize) -> Data {
|
||||||
self.stack[index]
|
self.stack[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn top(&self) -> &Data {
|
||||||
|
&self.stack[self.stack.len() - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put(&mut self, offset: usize, value: Data) {
|
||||||
|
self.stack[offset] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_fn(prog: &Program, proc: &Proc, superstack: &[Data]) -> Result<Option<Data>, ()> {
|
fn call_fn(prog: &Program, proc: &Proc, superstack: &[Data]) -> Result<Option<Data>, ()> {
|
||||||
|
@ -355,8 +459,9 @@ fn call_fn(prog: &Program, proc: &Proc, superstack: &[Data]) -> Result<Option<Da
|
||||||
stack.push(superstack[superstack.len() - i - 1].clone());
|
stack.push(superstack[superstack.len() - i - 1].clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
for instr in proc.code.iter() {
|
let mut x = 0;
|
||||||
match instr {
|
while x < proc.code.len() {
|
||||||
|
match &proc.code[x] {
|
||||||
Instr::Pop => {
|
Instr::Pop => {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
@ -368,11 +473,28 @@ fn call_fn(prog: &Program, proc: &Proc, superstack: &[Data]) -> Result<Option<Da
|
||||||
let v = stack.peek(*offset);
|
let v = stack.peek(*offset);
|
||||||
stack.push(v);
|
stack.push(v);
|
||||||
},
|
},
|
||||||
|
Instr::Store(offset) => {
|
||||||
|
let data = stack.top().clone();
|
||||||
|
stack.put(*offset, data);
|
||||||
|
},
|
||||||
Instr::Call(addr) => {
|
Instr::Call(addr) => {
|
||||||
if let Some(value) = call_fn(prog, prog.procs.get(addr).unwrap(), &stack.stack)? {
|
if let Some(value) = call_fn(prog, prog.procs.get(addr).unwrap(), &stack.stack)? {
|
||||||
stack.push(value);
|
stack.push(value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Instr::Jump(addr) => {
|
||||||
|
x = *addr - 1;
|
||||||
|
},
|
||||||
|
Instr::JumpUnless(addr) => {
|
||||||
|
match stack.pop() {
|
||||||
|
Some(Data::Bool(false)) => x = *addr - 1,
|
||||||
|
Some(Data::Bool(true)) => (),
|
||||||
|
_ => {
|
||||||
|
crate::message(crate::token::MessageType::Critical, "no condition for unless on stack");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
Instr::Operation(op) => {
|
Instr::Operation(op) => {
|
||||||
let op0:Data = if let Some(data) = stack.pop() {
|
let op0:Data = if let Some(data) = stack.pop() {
|
||||||
data
|
data
|
||||||
|
@ -461,6 +583,7 @@ fn call_fn(prog: &Program, proc: &Proc, superstack: &[Data]) -> Result<Option<Da
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
x += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(stack.pop())
|
Ok(stack.pop())
|
||||||
|
@ -480,7 +603,7 @@ pub fn execute(prog: &Program) -> Result<i64, ()> {
|
||||||
return Err(());
|
return Err(());
|
||||||
} else {
|
} else {
|
||||||
crate::message(
|
crate::message(
|
||||||
crate::token::MessageType::Critical,
|
crate::token::MessageType::Error,
|
||||||
"Program has no main() = int function",
|
"Program has no main() = int function",
|
||||||
);
|
);
|
||||||
return Err(());
|
return Err(());
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::io::Write;
|
||||||
|
|
||||||
fn print_to_file(file: &mut std::fs::File, prog: &crate::vmrt::Program) -> std::io::Result<()> {
|
fn print_to_file(file: &mut std::fs::File, prog: &crate::vmrt::Program) -> std::io::Result<()> {
|
||||||
for proc in prog.procs.iter() {
|
for proc in prog.procs.iter() {
|
||||||
writeln!(file, "\n0x{:#x}:", proc.0)?;
|
writeln!(file, "\n{:#x}:", proc.0)?;
|
||||||
|
|
||||||
for instr in proc.1.code.iter() {
|
for instr in proc.1.code.iter() {
|
||||||
writeln!(file, "{}", instr)?;
|
writeln!(file, "{}", instr)?;
|
||||||
|
|
46
test.erpn
46
test.erpn
|
@ -1,40 +1,10 @@
|
||||||
pi:
|
|
||||||
Load Rat 5.1415926535
|
|
||||||
foo:
|
|
||||||
Load Int 5
|
|
||||||
Load Int 6
|
|
||||||
Add Int
|
|
||||||
Store Int x
|
|
||||||
Load Arg x
|
|
||||||
Load Int 6
|
|
||||||
Lt Int
|
|
||||||
Unless
|
|
||||||
Load Bool true
|
|
||||||
Yield
|
|
||||||
Please
|
|
||||||
Load Arg x
|
|
||||||
Load Int 6
|
|
||||||
Lt Int
|
|
||||||
Unless
|
|
||||||
Load Bool true
|
|
||||||
Yield
|
|
||||||
Load Bool true
|
|
||||||
Yield
|
|
||||||
main:
|
main:
|
||||||
|
Load Int 2
|
||||||
Load Int 4
|
Load Int 4
|
||||||
Store Int a
|
Eq Int
|
||||||
Call pi
|
Unless
|
||||||
Store Rat b
|
Load Int 1
|
||||||
Load Bool true
|
Yield
|
||||||
Store Bool c
|
Load Int 0
|
||||||
Load Int 3
|
Yield
|
||||||
Load Rat 4.0
|
|
||||||
Call foo
|
|
||||||
Store Bool r
|
|
||||||
Load Int 3
|
|
||||||
Load Rat 5.0
|
|
||||||
Call foo
|
|
||||||
Store Bool h
|
|
||||||
Load Int 4
|
|
||||||
Store Int b
|
|
||||||
Load Int 9
|
|
||||||
|
|
Loading…
Reference in New Issue