Skip to content

Commit

Permalink
Merge branch 'next' into update-ast-to-compile-mast
Browse files Browse the repository at this point in the history
  • Loading branch information
vlopes11 committed Nov 11, 2022
2 parents 9636cdd + 9258eb3 commit 3430fdc
Show file tree
Hide file tree
Showing 24 changed files with 707 additions and 252 deletions.
8 changes: 8 additions & 0 deletions assembly/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ impl AssemblyError {
}
}

pub fn malformed_doc_comment(step: usize) -> Self {
AssemblyError {
message: "doc comments separated by line break".to_string(),
step,
op: "".to_string(),
}
}

// PROGRAM
// --------------------------------------------------------------------------------------------

Expand Down
21 changes: 13 additions & 8 deletions assembly/src/parsers/ast/context.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use crate::ProcedureId;

use super::{
io_ops, stack_ops, u32_ops, AssemblyError, Instruction, LocalProcMap, Node, ProcedureAst,
Token, TokenStream, MODULE_PATH_DELIM,
field_ops, io_ops, stack_ops, u32_ops, AssemblyError, Instruction, LocalProcMap, Node,
ProcedureAst, Token, TokenStream, MODULE_PATH_DELIM,
};
use crate::ProcedureId;
use vm_core::utils::{
collections::{BTreeMap, Vec},
string::{String, ToString},
Expand Down Expand Up @@ -223,6 +222,11 @@ impl ParserContext {
// read procedure name and consume the procedure header token
let header = tokens.read().expect("missing procedure header");
let (label, num_locals, is_export) = header.parse_proc()?;
let docs = if is_export {
tokens.take_doc_comment_at(proc_start)
} else {
None
};

tokens.advance();

Expand All @@ -247,6 +251,7 @@ impl ParserContext {
// build and return the procedure
let proc = ProcedureAst {
name: label,
docs,
num_locals,
is_export,
body,
Expand Down Expand Up @@ -337,15 +342,15 @@ fn parse_op_token(op: &Token) -> Result<Node, AssemblyError> {
"inv" => Node::Instruction(Instruction::Inv),

"pow2" => Node::Instruction(Instruction::Pow2),
"exp" => Node::Instruction(Instruction::Exp),
"exp" => field_ops::parse_exp(op)?,

"not" => Node::Instruction(Instruction::Not),
"and" => Node::Instruction(Instruction::And),
"or" => Node::Instruction(Instruction::Or),
"xor" => Node::Instruction(Instruction::Xor),

"eq" => Node::Instruction(Instruction::Eq),
"neq" => Node::Instruction(Instruction::Neq),
"eq" => field_ops::parse_eq(op)?,
"neq" => field_ops::parse_neq(op)?,
"lt" => Node::Instruction(Instruction::Lt),
"lte" => Node::Instruction(Instruction::Lte),
"gt" => Node::Instruction(Instruction::Gt),
Expand All @@ -355,7 +360,7 @@ fn parse_op_token(op: &Token) -> Result<Node, AssemblyError> {
// ----- u32 operations -------------------------------------------------------------------
"u32test" => Node::Instruction(Instruction::U32Test),
"u32testw" => Node::Instruction(Instruction::U32TestW),
"u32assert" => Node::Instruction(Instruction::U32Assert),
"u32assert" => u32_ops::parse_u32assert(op)?,
"u32assertw" => Node::Instruction(Instruction::U32AssertW),
"u32cast" => Node::Instruction(Instruction::U32Cast),
"u32split" => Node::Instruction(Instruction::U32Split),
Expand Down
65 changes: 65 additions & 0 deletions assembly/src/parsers/ast/field_ops.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use super::{
super::parse_bit_len_param, super::parse_element_param, AssemblyError, Instruction, Node,
Token, Vec,
};
use crate::validate_operation;

pub fn parse_exp(op: &Token) -> Result<Node, AssemblyError> {
let instruction = match op.num_parts() {
1 => Instruction::Exp,
2 => {
let param_value = op.parts()[1];

if param_value.strip_prefix('u').is_some() {
// parse the bits length of the exponent from the immediate value.
let bits_len = parse_bit_len_param(op, 1)?;

// the specified bits length can not be more than 64 bits.
if bits_len > 64 {
return Err(AssemblyError::invalid_param_with_reason(
op,
1,
format!("parameter can at max be a u64 but found u{}", bits_len).as_str(),
));
}

Instruction::ExpBitLength(bits_len as u8)
} else {
// parse immediate value.
let imm = parse_element_param(op, 1)?;
Instruction::ExpImm(imm)
}
}
_ => return Err(AssemblyError::extra_param(op)),
};

Ok(Node::Instruction(instruction))
}

pub fn parse_eq(op: &Token) -> Result<Node, AssemblyError> {
validate_operation!(op, "eq", 0..1);

let node = match op.num_parts() {
2 => {
let value = parse_element_param(op, 1)?;
Node::Instruction(Instruction::EqImm(value))
}
_ => Node::Instruction(Instruction::Eq),
};

Ok(node)
}

pub fn parse_neq(op: &Token) -> Result<Node, AssemblyError> {
validate_operation!(op, "neq", 0..1);

let node = match op.num_parts() {
2 => {
let value = parse_element_param(op, 1)?;
Node::Instruction(Instruction::NeqImm(value))
}
_ => Node::Instruction(Instruction::Neq),
};

Ok(node)
}
13 changes: 10 additions & 3 deletions assembly/src/parsers/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub(crate) use nodes::{Instruction, Node};
mod context;
use context::ParserContext;

mod field_ops;
mod io_ops;
mod serde;
mod stack_ops;
Expand Down Expand Up @@ -61,7 +62,7 @@ impl ProgramAst {
}

/// Returns a `ProgramAst` struct by its byte representation.
pub fn from_bytes(bytes: &mut &[u8]) -> Result<Self, SerializationError> {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, SerializationError> {
let mut byte_reader = ByteReader::new(bytes);

let num_local_procs = byte_reader.read_u16()?;
Expand Down Expand Up @@ -311,6 +312,7 @@ impl<'a> NamedModuleAst<'a> {
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct ProcedureAst {
pub name: String,
pub docs: Option<String>,
pub num_locals: u32,
pub body: Vec<Node>,
pub is_export: bool,
Expand All @@ -320,8 +322,11 @@ impl Serializable for ProcedureAst {
/// Writes byte representation of the `ProcedureAst` into the provided `ByteWriter` struct.
fn write_into(&self, target: &mut ByteWriter) {
target
.write_string(&self.name)
.write_proc_name(&self.name)
.expect("String serialization failure");
target
.write_docs(&self.docs)
.expect("Docs serialization failure");
target.write_bool(self.is_export);
target.write_u16(self.num_locals as u16);
self.body.write_into(target);
Expand All @@ -331,12 +336,14 @@ impl Serializable for ProcedureAst {
impl Deserializable for ProcedureAst {
/// Returns a `ProcedureAst` from its byte representation stored in provided `ByteReader` struct.
fn read_from(bytes: &mut ByteReader) -> Result<Self, SerializationError> {
let name = bytes.read_string()?;
let name = bytes.read_proc_name()?;
let docs = bytes.read_docs()?;
let is_export = bytes.read_bool()?;
let num_locals = bytes.read_u16()?.into();
let body = Deserializable::read_from(bytes)?;
Ok(ProcedureAst {
name,
docs,
num_locals,
body,
is_export,
Expand Down
4 changes: 4 additions & 0 deletions assembly/src/parsers/ast/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub enum Instruction {
Inv,
Pow2,
Exp,
ExpImm(Felt),
ExpBitLength(u8),
Not,
And,
Or,
Expand All @@ -53,6 +55,7 @@ pub enum Instruction {
U32Test,
U32TestW,
U32Assert,
U32Assert2,
U32AssertW,
U32Split,
U32Cast,
Expand Down Expand Up @@ -245,4 +248,5 @@ pub enum Instruction {
ExecImported(ProcedureId),
CallLocal(u16),
CallImported(ProcedureId),
SysCall(ProcedureId),
}
23 changes: 19 additions & 4 deletions assembly/src/parsers/ast/serde/deserialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,27 @@ impl<'a> ByteReader<'a> {
))
}

pub fn read_string(&mut self) -> Result<String, SerializationError> {
self.check_eor(1)?;
let length = self.bytes[self.pos];
self.pos += 1;
pub fn read_proc_name(&mut self) -> Result<String, SerializationError> {
let length = self.read_u8()?;
self.check_eor(length as usize)?;
let string_bytes = &self.bytes[self.pos..self.pos + length as usize];
self.pos += length as usize;
Ok(String::from_utf8(string_bytes.to_vec()).expect("String conversion failure"))
}

pub fn read_docs(&mut self) -> Result<Option<String>, SerializationError> {
let length = self.read_u16()?;
if length != 0 {
self.check_eor(length as usize)?;
let string_bytes = &self.bytes[self.pos..self.pos + length as usize];
self.pos += length as usize;
let docs = String::from_utf8(string_bytes.to_vec()).expect("String conversion failure");
Ok(Some(docs))
} else {
Ok(None)
}
}

pub fn read_procedure_id(&mut self) -> Result<ProcedureId, SerializationError> {
self.check_eor(ProcedureId::SIZE)?;
let mut hash = [0; ProcedureId::SIZE];
Expand Down Expand Up @@ -177,6 +188,8 @@ impl Deserializable for Instruction {
OpCode::Inv => Ok(Instruction::Inv),
OpCode::Pow2 => Ok(Instruction::Pow2),
OpCode::Exp => Ok(Instruction::Exp),
OpCode::ExpImm => Ok(Instruction::ExpImm(bytes.read_felt()?)),
OpCode::ExpBitLength => Ok(Instruction::ExpBitLength(bytes.read_u8()?)),
OpCode::Not => Ok(Instruction::Not),
OpCode::And => Ok(Instruction::And),
OpCode::Or => Ok(Instruction::Or),
Expand All @@ -195,6 +208,7 @@ impl Deserializable for Instruction {
OpCode::U32Test => Ok(Instruction::U32Test),
OpCode::U32TestW => Ok(Instruction::U32TestW),
OpCode::U32Assert => Ok(Instruction::U32Assert),
OpCode::U32Assert2 => Ok(Instruction::U32Assert2),
OpCode::U32AssertW => Ok(Instruction::U32AssertW),
OpCode::U32Split => Ok(Instruction::U32Split),
OpCode::U32Cast => Ok(Instruction::U32Cast),
Expand Down Expand Up @@ -400,6 +414,7 @@ impl Deserializable for Instruction {
OpCode::ExecImported => Ok(Instruction::ExecImported(bytes.read_procedure_id()?)),
OpCode::CallLocal => Ok(Instruction::CallLocal(bytes.read_u16()?)),
OpCode::CallImported => Ok(Instruction::CallImported(bytes.read_procedure_id()?)),
OpCode::SysCall => Ok(Instruction::SysCall(bytes.read_procedure_id()?)),
}
}
}
Expand Down
Loading

0 comments on commit 3430fdc

Please sign in to comment.