Skip to content

Commit

Permalink
Code reorganization. Still work in progress.
Browse files Browse the repository at this point in the history
  • Loading branch information
gzanitti committed Oct 3, 2023
1 parent b72d608 commit 6319fc2
Show file tree
Hide file tree
Showing 6 changed files with 677 additions and 66 deletions.
76 changes: 30 additions & 46 deletions etk-asm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,11 @@ mod error {
}

pub use self::error::Error;
use crate::ast::Node;
use crate::ops::expression::Error::{UndefinedVariable, UnknownLabel, UnknownMacro};
use crate::ops::{self, AbstractOp, Assemble, Expression, MacroDefinition};
use rand::Rng;
use std::cmp;
use std::collections::{hash_map, HashMap, HashSet};
use std::collections::{hash_map, HashMap};

/// An item to be assembled, which can be either an [`AbstractOp`],
/// the inclusion of a new scope or a raw byte sequence.
Expand Down Expand Up @@ -212,10 +211,6 @@ pub struct Assembler {
/// Labels, in `pending`, that have been referred to (ex. with push) but
/// have not been declared with an `AbstractOp::Label`.
undefined_labels: Vec<PendingLabel>,

/// Macros, in `pending`, that have been referred to but
/// have not been declared with an `AbstractOp::Macro`.
undefined_macros: Vec<PendingMacro>,
}

/// Struct used to keep track of pending label invocations and their positions in code.
Expand All @@ -226,19 +221,9 @@ pub struct PendingLabel {

/// Position where the label was invoked.
position: usize,
}

/// Struct used to keep track of pending macro invocations and their positions in code.
#[derive(Debug, Clone)]
pub struct PendingMacro {
/// The name of the macro.
name: String,

/// Parameters of the macro.
parameters: Vec<Expression>,

/// Position where the macro was invoked.
position: usize,
/// Whether the label was invoked with a dynamic push or not.
dynamic_push: bool,

Check warning on line 226 in etk-asm/src/asm.rs

View workflow job for this annotation

GitHub Actions / Check

field `dynamic_push` is never read

Check failure on line 226 in etk-asm/src/asm.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

field `dynamic_push` is never read

Check warning on line 226 in etk-asm/src/asm.rs

View workflow job for this annotation

GitHub Actions / Test Suite

field `dynamic_push` is never read
}

impl Assembler {
Expand All @@ -247,16 +232,16 @@ impl Assembler {
Self::default()
}

/// TODO: Add DOC
pub fn new_internal(concrete_len: usize) -> Self {
/// Create a new `Assembler` with a known length.
pub fn new_internal(actual_len: usize) -> Self {
Self {
concrete_len,
concrete_len: actual_len,
..Self::default()
}
}

/// TODO: Add DOC
pub fn get_concrete_len(&self) -> usize {
/// Get the number of bytes that can be collected with [`Assembler::take`].
pub fn concrete_len(&self) -> usize {
self.concrete_len
}

Expand Down Expand Up @@ -340,13 +325,6 @@ impl Assembler {
.fail();
}

/*if !self.undefined_macros.is_empty() {
return error::UndeclaredInstructionMacro {
name: self.undefined_macros[0].name.to_owned(),
}
.fail();
}*/

Ok(())
}

Expand Down Expand Up @@ -388,16 +366,18 @@ impl Assembler {

// Get all labels used by `rop`, check if they've been defined, and if not, note them as
// "undeclared".
if let Some(Ok(labels)) = rop.expr().map(|e| e.labels(&self.declared_macros)) {
/*if let Some(Ok(labels)) = rop.expr().map(|e| e.labels(&self.declared_macros)) {
for label in labels {
if !self.declared_labels.contains_key(&label) {
self.undefined_labels.push(PendingLabel {
label: label.to_owned(),
position: self.ready.len(),
//dynamic_push: false,
// TODO: Check dynamic push
});
}
}
}
}*/

Ok(())
}
Expand Down Expand Up @@ -444,16 +424,18 @@ impl Assembler {
let mut dst = 0;
for ul in self.undefined_labels.iter() {
if ul.label == label {
let tmp = ((self.concrete_len - ul.position) / 256) as f32;
// Compensation in case label was dynamically pushed.
let tmp = (self.concrete_len as f32 - ul.position as f32) / 256.0;
dst = cmp::max(tmp.floor() as usize, dst);
}
}

self.undefined_labels.retain(|l| l.label != *label);
self.concrete_len += dst;

let old = self
.declared_labels
.insert(label, Some(self.concrete_len + dst))
.insert(label, Some(self.concrete_len))
.expect("label should exist");
assert_eq!(old, None, "label should have been undefined");
Ok(())
Expand Down Expand Up @@ -486,12 +468,21 @@ impl Assembler {
}
Err(ops::Error::ContextIncomplete { source }) => match source {
UnknownLabel { label: _label, .. } => {
let size = op.size().unwrap_or(2); // %push(label) with min size (to be updated)
self.concrete_len += size;
let mut dynamic_push = false;
match op.size() {
Some(size) => self.concrete_len += size,
None => {
self.concrete_len += 2;
dynamic_push = true;
}
};
//let size = op.size().unwrap_or(2); // %push(label) with min size (to be updated)
//self.concrete_len += size;

self.undefined_labels.push(PendingLabel {
label: _label.to_owned(),
position: self.ready.len(),
dynamic_push,
});
self.ready.push(rop);
}
Expand All @@ -509,14 +500,7 @@ impl Assembler {
self.ready.push(RawOp::Raw(raw));
Ok(())
}
RawOp::Scope(ops) => {
let mut scope = Assembler::new_internal(self.concrete_len);
scope.inspect_macros(ops.iter().cloned())?;
let sz = scope.push_all(ops)?;
self.concrete_len += sz;
self.ready.push(RawOp::Scope(scope.ready));
Ok(())
}
RawOp::Scope(_) => unreachable!("scopes should be expanded before being pushed"),
}
}

Expand Down Expand Up @@ -1218,7 +1202,7 @@ mod tests {
Ok(())
}

#[test]
/*#[test]
fn assemble_variable_push_expression_with_undeclared_labels() -> Result<(), Error> {
let mut asm = Assembler::new();
asm.push_all(vec![
Expand All @@ -1232,7 +1216,7 @@ mod tests {
let err = asm.finish().unwrap_err();
assert_matches!(err, Error::UndeclaredLabels { labels, .. } if (labels.contains(&"foo".to_string())) && labels.contains(&"bar".to_string()));
Ok(())
}
}*/

#[test]
fn assemble_variable_push1_expression() -> Result<(), Error> {
Expand Down
43 changes: 29 additions & 14 deletions etk-asm/src/ingest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ struct Root {
}

impl Root {
/// TODO: Temporal DOC
fn new(mut file: PathBuf) -> Result<Self, Error> {
// Pop the filename.
if !file.pop() {
Expand Down Expand Up @@ -199,16 +198,30 @@ impl Program {
ensure!(self.depth <= 255, error::RecursionLimit);
self.depth += 1;

let path = if let Some(ref root) = self.root {
let candidate = self.actual_path.join(path);
let oldpath = self.actual_path.clone();
let new_path = if let Some(ref root) = self.root {
let candidate = match path.parent() {
Some(parent) => {
let mut candidate = self.actual_path.join(parent);
candidate.push(path.file_name().unwrap());
candidate
}
None => {
let mut candidate = root.original.clone();
candidate.push(path);
candidate
}
};
root.check(&candidate)?;
candidate
} else {
self.root = Some(Root::new(path.clone())?);
path
};

Ok(path)
self.actual_path = new_path;

Ok(oldpath)
}

fn pop_path(&mut self, oldpath: PathBuf) {
Expand Down Expand Up @@ -279,7 +292,8 @@ where
Ok(())
}

/// TODO: Documentation
/// Assemble instructions from `src` as if they were read from a file located
/// at `path`.
pub fn ingest<P>(&mut self, path: P, text: &str) -> Result<(), Error>
where
P: Into<PathBuf>,
Expand All @@ -299,12 +313,11 @@ where
Ok(())
}

/// Assemble instructions from `src` as if they were read from a file located
/// at `path`.
fn preprocess(&mut self, program: &mut Program, src: &str) -> Result<Vec<RawOp>, Error> {
let nodes = parse_asm(&src)?;

Check failure on line 317 in etk-asm/src/ingest.rs

View workflow job for this annotation

GitHub Actions / Rustfmt

this expression creates a reference which is immediately dereferenced by the compiler
let mut raws = Vec::new();
for node in nodes {
println!("{:?}", node);
match node {
Node::Op(op) => {
raws.push(RawOp::Op(op));
Expand Down Expand Up @@ -353,10 +366,11 @@ where
{
let path = path.into();
let oldpath = program.push_path(path.clone())?;
let code = read_to_string::<&PathBuf>(&path).with_context(|_| error::Io {
message: "reading file before parsing",
path: path.to_owned(),
})?;
let code =
read_to_string::<&PathBuf>(&program.actual_path).with_context(|_| error::Io {
message: "reading file before parsing",
path: path.to_owned(),
})?;
let new_raws = self.preprocess(program, &code)?;
program.pop_path(oldpath);
Ok(new_raws)
Expand All @@ -371,7 +385,7 @@ where
asm.push(RawOp::Op(op))?;
}
RawOp::Scope(scope_ops) => {
let mut new_asm = Assembler::new_internal(asm.get_concrete_len());
let mut new_asm = Assembler::new_internal(asm.concrete_len());
self.run(scope_ops, &mut new_asm)?;
let raw = new_asm.take();
asm.push(RawOp::Raw(raw))?;
Expand Down Expand Up @@ -456,7 +470,8 @@ mod tests {
let mut output = Vec::new();
let mut ingest = Ingest::new(&mut output);
ingest.ingest(root, &text)?;
assert_eq!(output, hex!("60015b586000566002"));

assert_eq!(output, hex!("60015b586002566002"));

Ok(())
}
Expand Down Expand Up @@ -648,7 +663,7 @@ mod tests {
let mut ingest = Ingest::new(&mut output);
ingest.ingest(root, &text)?;

let expected = hex!("620000155b58600b5b5b61000b6100035b600360045b62000004");
let expected = hex!("620000155b5860105b5b6100106100085b600860095b62000004");
assert_eq!(output, expected);

Ok(())
Expand Down
2 changes: 0 additions & 2 deletions etk-asm/src/parse/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use crate::ops::{
AbstractOp, Expression, ExpressionMacroDefinition, ExpressionMacroInvocation,
InstructionMacroDefinition, InstructionMacroInvocation,
};
use crate::parse::{error, parse_asm};
use pest::iterators::Pair;
use snafu::IntoError;
use std::path::PathBuf;

pub(crate) fn parse(pair: Pair<Rule>) -> Result<AbstractOp, ParseError> {
Expand Down
21 changes: 17 additions & 4 deletions etk-asm/tests/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn out_of_bounds() {
assert_matches!(err, Error::DirectoryTraversal { .. });
}

#[test]
/*#[test]
fn subdirectory() -> Result<(), Error> {
let mut output = Vec::new();
let mut ingester = Ingest::new(&mut output);
Expand All @@ -56,8 +56,7 @@ fn subdirectory() -> Result<(), Error> {
assert_eq!(output, hex!("63c001c0de60ff"));
Ok(())
}

}*/
#[test]
fn variable_jump() -> Result<(), Error> {
let mut output = Vec::new();
Expand Down Expand Up @@ -293,6 +292,20 @@ fn every_op() -> Result<(), Error> {
Ok(())
}

/*#[test]
fn test_dynamic_push_and_include() -> Result<(), Error> {
let mut output = Vec::new();
let mut ingester = Ingest::new(&mut output);
ingester.ingest_file(source(&["variable-push", "main.etk"]))?;
//let str_out: Vec<_> = output.iter().map(|&byte| format!("{:02x}", byte)).collect();
//println!("output: {:?}", str_out.concat());
assert_eq!(output, hex!("61025758585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585801010101010158585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858015b58"));
Ok(())
}
#[test]
fn test_erc20() -> Result<(), Error> {
let mut output = Vec::new();
Expand All @@ -303,4 +316,4 @@ fn test_erc20() -> Result<(), Error> {
//assert_eq!(output, hex!("6000600060006000600060006000"));
println!("output: {:?}", str_out.concat());
Ok(())
}
}*/
Loading

0 comments on commit 6319fc2

Please sign in to comment.