Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/brainfuck.fml
Original file line number Diff line number Diff line change
Expand Up @@ -810,4 +810,4 @@ interpreter(program(), false).eval();
// > mogami river
// >
// > -- yukko
// >
// >
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use_small_heuristics = "Max"
197 changes: 93 additions & 104 deletions src/bytecode/bytecode.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::io::{Write, Read};
use std::io::{Read, Write};

use super::serializable;
use super::serializable::*;
Expand Down Expand Up @@ -30,7 +30,7 @@ pub enum OpCode {
* [ProgramObject::Integer]: ../objects/enum.ProgramObject.html#variant.Integer
* [ProgramObject::Null]: ../objects/enum.ProgramObject.html#variant.Null
*/
Literal { index: /*Integer|Null|Boolean*/ ConstantPoolIndex }, // rename to constant
Literal { index: ConstantPoolIndex }, // rename to constant

/**
* ## Push the value of local variable onto stack
Expand All @@ -43,7 +43,7 @@ pub enum OpCode {
* [LocalFrame]: ../interpreter/struct.LocalFrame.html
* [OperandStack]: ../interpreter/struct.OperandStack.html
*/
// FIXME writing out all those links in each variant is not sustainable...
// FIXME writing out all those links in each variant is not sustainable...
GetLocal { index: LocalFrameIndex },

/**
Expand All @@ -64,7 +64,7 @@ pub enum OpCode {
*
* Serialized as opcode `0x0C`.
*/
GetGlobal { name: /*String*/ ConstantPoolIndex },
GetGlobal { name: ConstantPoolIndex },

/**
* ## Set the value of global variable to the top value from stack
Expand All @@ -74,7 +74,7 @@ pub enum OpCode {
*
* Serialized as opcode `0x0B`.
*/
SetGlobal { name: /*String*/ ConstantPoolIndex },
SetGlobal { name: ConstantPoolIndex },

/**
* ## Create a new (runtime) object
Expand All @@ -95,7 +95,7 @@ pub enum OpCode {
*
* Serialized as opcode `0x04`.
*/
Object { class: /*ProgramObject::Class*/ ConstantPoolIndex },
Object { class: ConstantPoolIndex },

/**
* ## Create a new array (runtime) object
Expand Down Expand Up @@ -140,7 +140,7 @@ pub enum OpCode {
* ## Call a member method
*
* Pops `arguments` values from the `OperandStack` for the arguments to the call. The last popped
*`RuntimeObject` from the `OperandStack` will be used as the method call's receiver.
*`RuntimeObject` from the `OperandStack` will be used as the method call's receiver.
* Afterwards, a `ProgramObject::String` object representing the name of the method to call is
* retrieved from the `ConstantPool` from the index specified by `name`.
*
Expand Down Expand Up @@ -187,7 +187,7 @@ pub enum OpCode {
*
* Serialized as opcode `0x00`.
*/
Label { name: /*String*/ ConstantPoolIndex },
Label { name: ConstantPoolIndex },

/**
* ## Print a formatted string
Expand All @@ -202,7 +202,7 @@ pub enum OpCode {
*
* Serialized as opcode `0x02`.
*/
Print { format: /*String*/ ConstantPoolIndex, arguments: Arity },
Print { format: ConstantPoolIndex, arguments: Arity },

/**
* ## Jump to a label
Expand All @@ -212,7 +212,7 @@ pub enum OpCode {
*
* Serialized as opcode `0x0E`.
*/
Jump { label: /*String*/ ConstantPoolIndex },
Jump { label: ConstantPoolIndex },

/**
* ## Conditionally jump to a label
Expand All @@ -223,7 +223,7 @@ pub enum OpCode {
*
* Serialized as opcode `0x0D`.
*/
Branch { label: /*String*/ ConstantPoolIndex },
Branch { label: ConstantPoolIndex },

/**
* ## Return from the current function or method
Expand All @@ -249,41 +249,38 @@ pub enum OpCode {
Drop,
}



impl Serializable for OpCode {

fn serialize<W: Write> (&self, sink: &mut W) -> anyhow::Result<()> {
fn serialize<W: Write>(&self, sink: &mut W) -> anyhow::Result<()> {
serializable::write_u8(sink, self.to_hex())?;

use OpCode::*;
match self {
Label { name } => { name.serialize(sink) },
Literal { index } => { index.serialize(sink) },
Label { name } => name.serialize(sink),
Literal { index } => index.serialize(sink),
Print { format, arguments } => {
format.serialize(sink)?;
arguments.serialize(sink)
},
Array => { Ok(()) },
Object { class } => { class.serialize(sink) },
GetField { name } => { name.serialize(sink) },
SetField { name } => { name.serialize(sink) },
}
Array => Ok(()),
Object { class } => class.serialize(sink),
GetField { name } => name.serialize(sink),
SetField { name } => name.serialize(sink),
CallMethod { name, arguments } => {
name.serialize(sink)?;
arguments.serialize(sink)
},
}
CallFunction { name: function, arguments } => {
function.serialize(sink)?;
arguments.serialize(sink)
},
SetLocal { index } => { index.serialize(sink) },
GetLocal { index } => { index.serialize(sink) },
SetGlobal { name } => { name.serialize(sink) },
GetGlobal { name } => { name.serialize(sink) },
Branch { label } => { label.serialize(sink) },
Jump { label } => { label.serialize(sink) },
Return => { Ok(()) },
Drop => { Ok(()) },
}
SetLocal { index } => index.serialize(sink),
GetLocal { index } => index.serialize(sink),
SetGlobal { name } => name.serialize(sink),
GetGlobal { name } => name.serialize(sink),
Branch { label } => label.serialize(sink),
Jump { label } => label.serialize(sink),
Return => Ok(()),
Drop => Ok(()),
// Skip => { Ok(()) },
}
}
Expand All @@ -293,52 +290,58 @@ impl Serializable for OpCode {

use OpCode::*;
match tag {
0x00 => Label { name: ConstantPoolIndex::from_bytes(input) },
0x01 => Literal { index: ConstantPoolIndex::from_bytes(input) },
0x02 => Print { format: ConstantPoolIndex::from_bytes(input),
arguments: Arity::from_bytes(input) },
0x03 => Array { },
0x04 => Object { class: ConstantPoolIndex::from_bytes(input) },
0x05 => GetField { name: ConstantPoolIndex::from_bytes(input) },
0x06 => SetField { name: ConstantPoolIndex::from_bytes(input) },
0x07 => CallMethod { name: ConstantPoolIndex::from_bytes(input),
arguments: Arity::from_bytes(input) },
0x08 => CallFunction { name: ConstantPoolIndex::from_bytes(input),
arguments: Arity::from_bytes(input) },
0x09 => SetLocal { index: LocalFrameIndex::from_bytes(input) },
0x0A => GetLocal { index: LocalFrameIndex::from_bytes(input) },
0x0B => SetGlobal { name: ConstantPoolIndex::from_bytes(input) },
0x0C => GetGlobal { name: ConstantPoolIndex::from_bytes(input) },
0x0D => Branch { label: ConstantPoolIndex::from_bytes(input) },
0x0E => Jump { label: ConstantPoolIndex::from_bytes(input) },
0x00 => Label { name: ConstantPoolIndex::from_bytes(input) },
0x01 => Literal { index: ConstantPoolIndex::from_bytes(input) },
0x02 => Print {
format: ConstantPoolIndex::from_bytes(input),
arguments: Arity::from_bytes(input),
},
0x03 => Array {},
0x04 => Object { class: ConstantPoolIndex::from_bytes(input) },
0x05 => GetField { name: ConstantPoolIndex::from_bytes(input) },
0x06 => SetField { name: ConstantPoolIndex::from_bytes(input) },
0x07 => CallMethod {
name: ConstantPoolIndex::from_bytes(input),
arguments: Arity::from_bytes(input),
},
0x08 => CallFunction {
name: ConstantPoolIndex::from_bytes(input),
arguments: Arity::from_bytes(input),
},
0x09 => SetLocal { index: LocalFrameIndex::from_bytes(input) },
0x0A => GetLocal { index: LocalFrameIndex::from_bytes(input) },
0x0B => SetGlobal { name: ConstantPoolIndex::from_bytes(input) },
0x0C => GetGlobal { name: ConstantPoolIndex::from_bytes(input) },
0x0D => Branch { label: ConstantPoolIndex::from_bytes(input) },
0x0E => Jump { label: ConstantPoolIndex::from_bytes(input) },
0x0F => Return,
0x10 => Drop,
tag => panic!("Cannot deserialize opcode: unknown tag {}", tag)
tag => panic!("Cannot deserialize opcode: unknown tag {}", tag),
}
}
}

impl OpCode {
pub fn to_hex(&self) -> u8 {
pub fn to_hex(self) -> u8 {
use OpCode::*;
match self {
Label { name: _ } => 0x00,
Literal { index: _ } => 0x01,
Print { format: _, arguments: _ } => 0x02,
Array { } => 0x03,
Object { class: _ } => 0x04,
GetField { name: _ } => 0x05,
SetField { name: _ } => 0x06,
CallMethod { name: _, arguments: _ } => 0x07,
Label { name: _ } => 0x00,
Literal { index: _ } => 0x01,
Print { format: _, arguments: _ } => 0x02,
Array {} => 0x03,
Object { class: _ } => 0x04,
GetField { name: _ } => 0x05,
SetField { name: _ } => 0x06,
CallMethod { name: _, arguments: _ } => 0x07,
CallFunction { name: _, arguments: _ } => 0x08,
SetLocal { index: _ } => 0x09,
GetLocal { index: _ } => 0x0A,
SetGlobal { name: _ } => 0x0B,
GetGlobal { name: _ } => 0x0C,
Branch { label: _ } => 0x0D,
Jump { label: _ } => 0x0E,
Return => 0x0F,
Drop => 0x10,
SetLocal { index: _ } => 0x09,
GetLocal { index: _ } => 0x0A,
SetGlobal { name: _ } => 0x0B,
GetGlobal { name: _ } => 0x0C,
Branch { label: _ } => 0x0D,
Jump { label: _ } => 0x0E,
Return => 0x0F,
Drop => 0x10,
// Skip => 0xFF,
}
}
Expand All @@ -352,7 +355,10 @@ impl OpCode {
opcodes
}

pub fn write_opcode_vector<W: Write>(sink: &mut W, vector: &Vec<&OpCode>) -> anyhow::Result<()> {
pub fn write_opcode_vector<W: Write>(
sink: &mut W,
vector: &Vec<&OpCode>,
) -> anyhow::Result<()> {
serializable::write_usize_as_u32(sink, vector.len())?;
for opcode in vector {
opcode.serialize(sink)?;
Expand All @@ -364,40 +370,23 @@ impl OpCode {
impl std::fmt::Display for OpCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
OpCode::Literal { index } =>
write!(f, "lit {}", index),
OpCode::GetLocal { index } =>
write!(f, "get local {}", index),
OpCode::SetLocal { index } =>
write!(f, "set local {}", index),
OpCode::GetGlobal { name } =>
write!(f, "get global {}", name),
OpCode::SetGlobal { name } =>
write!(f, "set global {}", name),
OpCode::Object { class } =>
write!(f, "object {}", class),
OpCode::Array =>
write!(f, "array"),
OpCode::GetField { name } =>
write!(f, "get slot {}", name),
OpCode::SetField { name } =>
write!(f, "set slot {}", name),
OpCode::CallMethod { name, arguments } =>
write!(f, "call slot {} {}", name, arguments),
OpCode::CallFunction { name, arguments } =>
write!(f, "call {} {}", name, arguments),
OpCode::Print { format, arguments } =>
write!(f, "printf {} {}", format, arguments),
OpCode::Label { name } =>
write!(f, "label {}", name),
OpCode::Jump { label } =>
write!(f, "goto {}", label),
OpCode::Branch { label } =>
write!(f, "branch {}", label),
OpCode::Return =>
write!(f, "return"),
OpCode::Drop =>
write!(f, "drop"),
OpCode::Literal { index } => write!(f, "lit {}", index),
OpCode::GetLocal { index } => write!(f, "get local {}", index),
OpCode::SetLocal { index } => write!(f, "set local {}", index),
OpCode::GetGlobal { name } => write!(f, "get global {}", name),
OpCode::SetGlobal { name } => write!(f, "set global {}", name),
OpCode::Object { class } => write!(f, "object {}", class),
OpCode::Array => write!(f, "array"),
OpCode::GetField { name } => write!(f, "get slot {}", name),
OpCode::SetField { name } => write!(f, "set slot {}", name),
OpCode::CallMethod { name, arguments } => write!(f, "call slot {} {}", name, arguments),
OpCode::CallFunction { name, arguments } => write!(f, "call {} {}", name, arguments),
OpCode::Print { format, arguments } => write!(f, "printf {} {}", format, arguments),
OpCode::Label { name } => write!(f, "label {}", name),
OpCode::Jump { label } => write!(f, "goto {}", label),
OpCode::Branch { label } => write!(f, "branch {}", label),
OpCode::Return => write!(f, "return"),
OpCode::Drop => write!(f, "drop"),
}
}
}
}
Loading