added vmrt module
This commit is contained in:
parent
fda09066c7
commit
e80a69fb41
14
src/main.rs
14
src/main.rs
|
@ -6,6 +6,7 @@ mod parser;
|
||||||
// designed for a virtual stack machiene
|
// designed for a virtual stack machiene
|
||||||
mod inter;
|
mod inter;
|
||||||
mod conf;
|
mod conf;
|
||||||
|
mod vmrt;
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use parser::*;
|
use parser::*;
|
||||||
|
@ -47,10 +48,13 @@ foo(x:int, y:rat) = bool {
|
||||||
main() = int {
|
main() = int {
|
||||||
|
|
||||||
a = 4
|
a = 4
|
||||||
b = 5.5
|
b = pi
|
||||||
c = true
|
c = true
|
||||||
r = foo(3, ffalsee)
|
r = foo(3, 4.0)
|
||||||
0
|
h = foo(3,5.0)
|
||||||
|
b:int = 4
|
||||||
|
|
||||||
|
9
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
||||||
|
@ -59,7 +63,9 @@ main() = int {
|
||||||
let settings = conf::parse_args(&mut diagnostics);
|
let settings = conf::parse_args(&mut diagnostics);
|
||||||
|
|
||||||
if let Ok(mut tokens) = tokenize(source, &mut diagnostics) {
|
if let Ok(mut tokens) = tokenize(source, &mut diagnostics) {
|
||||||
parse(&mut tokens, &mut diagnostics, &settings);
|
if let Ok((fs, ds)) = parse(&mut tokens, &mut diagnostics, &settings) {
|
||||||
|
vmrt::compile(&fs, &ds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{}", diagnostics);
|
println!("{}", diagnostics);
|
||||||
|
|
|
@ -2,6 +2,8 @@ use crate::token::{DebugInfo, DebugNotice, Token, MessageType};
|
||||||
use crate::Prim;
|
use crate::Prim;
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum LogLvl {
|
pub enum LogLvl {
|
||||||
|
@ -127,7 +129,9 @@ pub struct Declr<'a> {
|
||||||
pub result_typ: Option<Prim>,
|
pub result_typ: Option<Prim>,
|
||||||
|
|
||||||
/// debug info
|
/// debug info
|
||||||
pub info: Option<DebugInfo>
|
pub info: Option<DebugInfo>,
|
||||||
|
|
||||||
|
uuid: u64
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Declr<'a> {
|
impl<'a> Declr<'a> {
|
||||||
|
@ -138,8 +142,39 @@ impl<'a> Declr<'a> {
|
||||||
results: false,
|
results: false,
|
||||||
result_typ: None,
|
result_typ: None,
|
||||||
info: None,
|
info: None,
|
||||||
|
uuid: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_arg_ord(&self, name: &str) -> usize {
|
||||||
|
if let Some(args) = self.args.as_ref() {
|
||||||
|
for (x, arg) in args.iter().enumerate() {
|
||||||
|
if arg.0 == name {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_uuid(&mut self) {
|
||||||
|
let mut hasher = DefaultHasher::default();
|
||||||
|
|
||||||
|
self.name.unwrap().hash(&mut hasher);
|
||||||
|
|
||||||
|
if let Some(args) = self.args.as_ref() {
|
||||||
|
for arg in args.iter() {
|
||||||
|
arg.0.hash(&mut hasher);
|
||||||
|
arg.1.hash(&mut hasher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.uuid = hasher.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uuid(&self) -> u64 {
|
||||||
|
self.uuid
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::fmt::Display for Declr<'a> {
|
impl<'a> std::fmt::Display for Declr<'a> {
|
||||||
|
|
|
@ -44,6 +44,8 @@ fn discover_functions<'a>(
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declr.gen_uuid();
|
||||||
|
|
||||||
// store new function and its declaration
|
// store new function and its declaration
|
||||||
funcs.push(func);
|
funcs.push(func);
|
||||||
declrs.push(declr);
|
declrs.push(declr);
|
||||||
|
@ -134,7 +136,7 @@ fn discover_functions<'a>(
|
||||||
|
|
||||||
if func.raw.is_none() {
|
if func.raw.is_none() {
|
||||||
match &top {
|
match &top {
|
||||||
Token::Operator(op, _) => match op {
|
Token::Operator(op, _, _) => match op {
|
||||||
Operator::Assign => {
|
Operator::Assign => {
|
||||||
// check if we already have an assign
|
// check if we already have an assign
|
||||||
if declr.results {
|
if declr.results {
|
||||||
|
@ -458,7 +460,7 @@ fn process_keyword(
|
||||||
|
|
||||||
if let Some(operand) = operands.pop() {
|
if let Some(operand) = operands.pop() {
|
||||||
if let Some(typ) = scope.func_return_typ {
|
if let Some(typ) = scope.func_return_typ {
|
||||||
if typ != operand {
|
if !typ.is_equal(operand) {
|
||||||
diagnostics.set_err(
|
diagnostics.set_err(
|
||||||
info,
|
info,
|
||||||
crate::msg::ERR59,
|
crate::msg::ERR59,
|
||||||
|
@ -491,7 +493,7 @@ fn collapse_operation(
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
|
|
||||||
match operation {
|
match operation {
|
||||||
Token::Operator(op, dbginf) => op.operate(operands, &dbginf, diagnostics)?,
|
Token::Operator(op, _, dbginf) => op.operate(operands, &dbginf, diagnostics)?,
|
||||||
Token::Assign(name, ref mut typ, dbginf) => {
|
Token::Assign(name, ref mut typ, dbginf) => {
|
||||||
check_var_typ(typ, operands, &dbginf, diagnostics)?;
|
check_var_typ(typ, operands, &dbginf, diagnostics)?;
|
||||||
scope.decl_var((*name).to_owned(), typ.clone());
|
scope.decl_var((*name).to_owned(), typ.clone());
|
||||||
|
@ -660,11 +662,11 @@ fn parse_term<'a>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Token::Operator(op, _) => {
|
Token::Operator(op, _, _) => {
|
||||||
let prec0 = op.prec();
|
let prec0 = op.prec();
|
||||||
while let Some(mut top) = op_stack.last_mut() {
|
while let Some(mut top) = op_stack.last_mut() {
|
||||||
match &top {
|
match &top {
|
||||||
Token::Operator(op1, _) => {
|
Token::Operator(op1, _, _) => {
|
||||||
let prec1 = op1.prec();
|
let prec1 = op1.prec();
|
||||||
|
|
||||||
if prec1 > prec0 || prec0 == prec1 && op.assoc() == Assoc::Left {
|
if prec1 > prec0 || prec0 == prec1 && op.assoc() == Assoc::Left {
|
||||||
|
@ -712,7 +714,9 @@ fn parse_term<'a>(
|
||||||
scope.expr_yield = value_stack.len() == 1;
|
scope.expr_yield = value_stack.len() == 1;
|
||||||
if scope.expr_yield {
|
if scope.expr_yield {
|
||||||
let yielded = value_stack.pop().unwrap();
|
let yielded = value_stack.pop().unwrap();
|
||||||
|
|
||||||
if !yielded.is_equal(scope.func_return_typ.unwrap()) {
|
if !yielded.is_equal(scope.func_return_typ.unwrap()) {
|
||||||
|
|
||||||
diagnostics.set_err(
|
diagnostics.set_err(
|
||||||
&output[0],
|
&output[0],
|
||||||
crate::msg::ERR59,
|
crate::msg::ERR59,
|
||||||
|
@ -722,7 +726,7 @@ fn parse_term<'a>(
|
||||||
yielded
|
yielded
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
panic!();
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,16 +797,16 @@ fn parse_exprs<'a>(
|
||||||
/// reorder and organize a listing of instructions to a RPN based format:
|
/// reorder and organize a listing of instructions to a RPN based format:
|
||||||
/// any program is made out of functions.
|
/// any program is made out of functions.
|
||||||
/// A function has a name followed by an optional parameter list, followed by an optional equal sign and block.
|
/// A function has a name followed by an optional parameter list, followed by an optional equal sign and block.
|
||||||
pub fn parse<'a>(tokens: &mut VecDeque<crate::Token<'a>>, diagnostics: &mut data::Diagnostics, settings: &Settings) {
|
pub fn parse<'a>(tokens: &mut VecDeque<crate::Token<'a>>, diagnostics: &mut data::Diagnostics, settings: &Settings) -> Result<(Vec<Func<'a>>, Vec<Declr<'a>>), ()> {
|
||||||
|
|
||||||
if let Ok((mut funcs, declrs)) = discover_functions(tokens, diagnostics) {
|
let (mut funcs, declrs) = discover_functions(tokens, diagnostics)?;
|
||||||
if let Ok(()) = discover_exprs(&mut funcs, &declrs, diagnostics) {
|
|
||||||
if let Ok(()) = parse_exprs(&mut funcs, &declrs, diagnostics) {
|
discover_exprs(&mut funcs, &declrs, diagnostics)?;
|
||||||
|
parse_exprs(&mut funcs, &declrs, diagnostics)?;
|
||||||
|
|
||||||
if settings.gen_erpn() {
|
if settings.gen_erpn() {
|
||||||
crate::inter::convert_to_erpn(&mut funcs, &declrs);
|
crate::inter::convert_to_erpn(&mut funcs, &declrs);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
return Ok((funcs, declrs));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,6 +163,7 @@ impl Operator {
|
||||||
info: &DebugInfo,
|
info: &DebugInfo,
|
||||||
diagnostics: &mut crate::parser::data::Diagnostics,
|
diagnostics: &mut crate::parser::data::Diagnostics,
|
||||||
) -> Result<(),()> {
|
) -> Result<(),()> {
|
||||||
|
// TODO: insert type hint
|
||||||
match self {
|
match self {
|
||||||
Operator::Add | Operator::Sub | Operator::Mul | Operator::Div => {
|
Operator::Add | Operator::Sub | Operator::Mul | Operator::Div => {
|
||||||
let types_valid =
|
let types_valid =
|
||||||
|
@ -459,7 +460,7 @@ pub enum Token<'a> {
|
||||||
Word(&'a str, DebugInfo),
|
Word(&'a str, DebugInfo),
|
||||||
/// Single symbol delemiter like ```(```,```}```
|
/// Single symbol delemiter like ```(```,```}```
|
||||||
Delemiter(char, DebugInfo),
|
Delemiter(char, DebugInfo),
|
||||||
Operator(Operator, DebugInfo),
|
Operator(Operator, Option<Prim>, DebugInfo),
|
||||||
Number(&'a str, NumHint, DebugInfo),
|
Number(&'a str, NumHint, DebugInfo),
|
||||||
LineBreak(DebugInfo),
|
LineBreak(DebugInfo),
|
||||||
Func(&'a str, DebugInfo),
|
Func(&'a str, DebugInfo),
|
||||||
|
@ -485,7 +486,7 @@ impl<'a> std::fmt::Display for Token<'a> {
|
||||||
Token::Type(t, _) => f.write_fmt(format_args!("__Type {:?}", t)),
|
Token::Type(t, _) => f.write_fmt(format_args!("__Type {:?}", t)),
|
||||||
Token::Word(w, _) => f.write_fmt(format_args!("__Word {:?}", w)),
|
Token::Word(w, _) => f.write_fmt(format_args!("__Word {:?}", w)),
|
||||||
Token::Delemiter(d, _) => f.write_fmt(format_args!("__Delemiter {:?}", d)),
|
Token::Delemiter(d, _) => f.write_fmt(format_args!("__Delemiter {:?}", d)),
|
||||||
Token::Operator(o, _) => f.write_fmt(format_args!("{:?}", o)),
|
Token::Operator(o, _, _) => f.write_fmt(format_args!("{:?}", o)),
|
||||||
Token::Number(n, hint, _) => f.write_fmt(format_args!("Load {:?} {}", hint, n)),
|
Token::Number(n, hint, _) => f.write_fmt(format_args!("Load {:?} {}", hint, n)),
|
||||||
Token::LineBreak(_) => f.write_str("__Line-break"),
|
Token::LineBreak(_) => f.write_str("__Line-break"),
|
||||||
Token::Func(name, _) => f.write_fmt(format_args!("Call {}", name)),
|
Token::Func(name, _) => f.write_fmt(format_args!("Call {}", name)),
|
||||||
|
@ -506,7 +507,7 @@ impl<'a> Into<DebugInfo> for Token<'a> {
|
||||||
Token::Type(_, d) => d,
|
Token::Type(_, d) => d,
|
||||||
Token::Word(_, d) => d,
|
Token::Word(_, d) => d,
|
||||||
Token::Delemiter(_, d) => d,
|
Token::Delemiter(_, d) => d,
|
||||||
Token::Operator(_, d) => d,
|
Token::Operator(_, _, d) => d,
|
||||||
Token::Number(_, _, d) => d,
|
Token::Number(_, _, d) => d,
|
||||||
Token::LineBreak(d) => d,
|
Token::LineBreak(d) => d,
|
||||||
Token::Func(_, d) => d,
|
Token::Func(_, d) => d,
|
||||||
|
@ -577,7 +578,7 @@ pub fn tokenize<'a>(source: &'a str, diagnostics: &mut Diagnostics) -> Result<Ve
|
||||||
}
|
}
|
||||||
9 => Token::Word(mat.as_str(), debug_info),
|
9 => Token::Word(mat.as_str(), debug_info),
|
||||||
10 => Token::Number(mat.as_str(), NumHint::from(mat.as_str()), debug_info),
|
10 => Token::Number(mat.as_str(), NumHint::from(mat.as_str()), debug_info),
|
||||||
11 => Token::Operator(Operator::parse(mat.as_str()), debug_info),
|
11 => Token::Operator(Operator::parse(mat.as_str()), None, debug_info),
|
||||||
12 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap(), debug_info),
|
12 => Token::Delemiter(mat.as_str().chars().nth(0).unwrap(), debug_info),
|
||||||
13 => {
|
13 => {
|
||||||
line_count += 1;
|
line_count += 1;
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
use std::collections::{VecDeque, HashMap};
|
||||||
|
|
||||||
|
use crate::{parser::data::*, token::{Token, NumHint}};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Data {
|
||||||
|
Int(i64),
|
||||||
|
Rat(f64),
|
||||||
|
Bool(bool),
|
||||||
|
Off(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum IntOp {
|
||||||
|
CmpEq,
|
||||||
|
CmpNEq,
|
||||||
|
CmpLt,
|
||||||
|
CmpGt,
|
||||||
|
CmpLtEq,
|
||||||
|
CmpGtEq,
|
||||||
|
|
||||||
|
Add,
|
||||||
|
Sub,
|
||||||
|
Mul,
|
||||||
|
Div
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum RatOp {
|
||||||
|
CmpEq,
|
||||||
|
CmpNEq,
|
||||||
|
CmpLt,
|
||||||
|
CmpGt,
|
||||||
|
CmpLtEq,
|
||||||
|
CmpGtEq,
|
||||||
|
|
||||||
|
Add,
|
||||||
|
Sub,
|
||||||
|
Mul,
|
||||||
|
Div
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum BoolOp {
|
||||||
|
CmpEq,
|
||||||
|
CmpNEq,
|
||||||
|
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
Xor
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Operation {
|
||||||
|
Int(IntOp),
|
||||||
|
Rat(RatOp),
|
||||||
|
Bool(BoolOp)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Instr {
|
||||||
|
/// load some data onto the stack
|
||||||
|
Push(Data),
|
||||||
|
/// delete the last value from stack
|
||||||
|
Pop,
|
||||||
|
|
||||||
|
/// push the value stored at offset onto the stack
|
||||||
|
Load(usize),
|
||||||
|
/// store the value stored at the stack[0](offset) stack[1](value) onto the stack
|
||||||
|
Store,
|
||||||
|
|
||||||
|
Call(u64),
|
||||||
|
|
||||||
|
Return,
|
||||||
|
|
||||||
|
Operation(Operation),
|
||||||
|
|
||||||
|
Exit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// function stack layout
|
||||||
|
/// +----------------------------------+
|
||||||
|
/// | Return address |
|
||||||
|
/// +----------------------------------+
|
||||||
|
/// | Parameter (0) |
|
||||||
|
/// +----------------------------------+
|
||||||
|
/// | Parameter (1) |
|
||||||
|
/// +----------------------------------+
|
||||||
|
/// | Parameter (2) |
|
||||||
|
/// +----------------------------------+
|
||||||
|
/// | Parameter (n) |
|
||||||
|
/// +----------------------------------+
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Program {
|
||||||
|
code: HashMap<u64, Vec<Instr>>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Compiletime<'a> {
|
||||||
|
vartable: HashMap<&'a str, usize>,
|
||||||
|
stacksize: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_term<'a>(term: &VecDeque<Token<'a>>, x: usize, declr: &Vec<Declr<'a>>, ct: &mut Compiletime<'a>, code: &mut Vec<Instr>) {
|
||||||
|
for token in term.iter() {
|
||||||
|
let instr = match token {
|
||||||
|
Token::Number(value, hint, _) => {
|
||||||
|
code.push(Instr::Push(match hint {
|
||||||
|
NumHint::Int => Data::Int(value.parse::<i64>().unwrap()),
|
||||||
|
NumHint::Rat => Data::Rat(value.parse::<f64>().unwrap()),
|
||||||
|
}));
|
||||||
|
ct.stacksize += 1;
|
||||||
|
},
|
||||||
|
Token::Bool(value, _) => {
|
||||||
|
code.push(Instr::Push(Data::Bool(*value)));
|
||||||
|
ct.stacksize += 1;
|
||||||
|
},
|
||||||
|
Token::Arg(name, _) => {
|
||||||
|
let off = declr[x].get_arg_ord(name);
|
||||||
|
|
||||||
|
code.push(Instr::Load(off + 1));
|
||||||
|
ct.stacksize += 1;
|
||||||
|
},
|
||||||
|
Token::Assign(name, _, _) => {
|
||||||
|
ct.vartable.insert(name.clone(), ct.stacksize - 1);
|
||||||
|
},
|
||||||
|
Token::Var(name, _) => {
|
||||||
|
code.push(Instr::Load(*ct.vartable.get(name).unwrap()));
|
||||||
|
ct.stacksize += 1;
|
||||||
|
}
|
||||||
|
Token::Operator(op, _, _) => {
|
||||||
|
code.push(match op {
|
||||||
|
crate::token::Operator::Or => Instr::Operation(Operation::Bool(BoolOp::Or)),
|
||||||
|
crate::token::Operator::And => Instr::Operation(Operation::Bool(BoolOp::And)),
|
||||||
|
crate::token::Operator::Xor => Instr::Operation(Operation::Bool(BoolOp::Xor)),
|
||||||
|
|
||||||
|
_ => panic!()
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: operatiors
|
||||||
|
// we pop 2 values as arguments and push 1 as result (-2 + 1 = 1)
|
||||||
|
ct.stacksize -= 1;
|
||||||
|
},
|
||||||
|
Token::Func(name, _) => {
|
||||||
|
for decl in declr.iter() {
|
||||||
|
if decl.name.as_ref().unwrap() == name {
|
||||||
|
code.push(Instr::Call(decl.uuid()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Token::Keyword(keyword, _) => {
|
||||||
|
match keyword {
|
||||||
|
crate::token::Keyword::Yield | crate::token::Keyword::Return => code.push(Instr::Return),
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_ => ()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_block<'a>(block: &VecDeque<Expr<'a>>, x: usize, declr: &Vec<Declr<'a>>, ct: &mut Compiletime<'a>, prog: &mut Vec<Instr>) {
|
||||||
|
for expr in block.iter() {
|
||||||
|
compile_expr(expr, x, declr, ct, prog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_expr<'a>(expr: &Expr<'a>, x: usize, declr: &Vec<Declr<'a>>, ct: &mut Compiletime<'a>, prog: &mut Vec<Instr>) {
|
||||||
|
match expr {
|
||||||
|
Expr::Block(block) => parse_block(block, x, declr, ct, prog),
|
||||||
|
Expr::Term(term) => parse_term(term, x, declr, ct, prog),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile<'a>(funcs: &Vec<Func<'a>>, declrs: &Vec<Declr<'a>>) {
|
||||||
|
let mut prog = Program::default();
|
||||||
|
|
||||||
|
for (x, func) in funcs.iter().enumerate() {
|
||||||
|
let mut code = vec![];
|
||||||
|
let mut ct = Compiletime::default();
|
||||||
|
|
||||||
|
// at beginn the is the return address and the parameter on the stack
|
||||||
|
ct.stacksize = declrs[x].args.as_ref().unwrap_or(&vec![]).len() + 1;
|
||||||
|
|
||||||
|
compile_expr(func.expr.as_ref().unwrap(), x, declrs, &mut ct, &mut code);
|
||||||
|
|
||||||
|
println!("{:#?}", code);
|
||||||
|
|
||||||
|
prog.code.insert(declrs[x].uuid(), code);
|
||||||
|
}
|
||||||
|
}
|
12
test.erpn
12
test.erpn
|
@ -23,12 +23,18 @@ foo:
|
||||||
main:
|
main:
|
||||||
Load Int 4
|
Load Int 4
|
||||||
Store Int a
|
Store Int a
|
||||||
Load Rat 5.5
|
Call pi
|
||||||
Store Rat b
|
Store Rat b
|
||||||
Load Bool true
|
Load Bool true
|
||||||
Store Bool c
|
Store Bool c
|
||||||
Load Int 3
|
Load Int 3
|
||||||
Load Rat 3.4
|
Load Rat 4.0
|
||||||
Call foo
|
Call foo
|
||||||
Store Bool r
|
Store Bool r
|
||||||
Load Int 0
|
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