Skip to content
This repository has been archived by the owner on Dec 10, 2023. It is now read-only.

Commit

Permalink
add the String and Unknown value types
Browse files Browse the repository at this point in the history
  • Loading branch information
hlorenzi committed Sep 3, 2021
1 parent 3d61bc5 commit 4e1426c
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 67 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "customasm"
version = "0.11.10"
version = "0.12.0"
edition = "2018"
authors = ["hlorenzi <https://hlorenzi.com>"]
description = "An assembler for custom, user-defined instruction sets!"
Expand Down
4 changes: 2 additions & 2 deletions src/asm/parser/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ pub fn parse_directive_data(
Some(elem_size) => invocation.size_guess = elem_size,
None =>
{
invocation.size_guess = match resolved
invocation.size_guess = match resolved.map(|r| r.get_bigint())
{
Ok(expr::Value::Integer(bigint)) =>
Ok(Some(bigint)) =>
{
match bigint.size
{
Expand Down
84 changes: 62 additions & 22 deletions src/asm/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,9 +500,9 @@ impl State
_ => unreachable!(),
};

let (bigint, size) = match resolved
let (bigint, size) = match resolved.get_bigint()
{
expr::Value::Integer(bigint) =>
Some(bigint) =>
{
match bigint.size
{
Expand Down Expand Up @@ -536,7 +536,7 @@ impl State
}
}

_ =>
None =>
{
report.error_span(
format!(
Expand Down Expand Up @@ -1036,7 +1036,7 @@ impl State
}
else if self.is_first_pass
{
Ok(expr::Value::make_integer(0))
Ok(expr::Value::Unknown)
}
else
{
Expand Down Expand Up @@ -1077,52 +1077,88 @@ impl State
expr::Value::Bool(value) => Ok(value),
_ =>
{
info.report.error_span("expected boolean argument", info.span);
info.report.error_span("expected boolean argument", &info.arg_spans[index]);
Err(true)
}
}
}


fn eval_fn_get_bigint_arg<'a>(
fn eval_fn_check_unknown_arg<'a>(
info: &'a expr::EvalFunctionInfo,
index: usize,
is_first_pass: bool)
-> bool
{
if !is_first_pass
{
return false;
}

match &info.args[index]
{
expr::Value::Unknown => true,
_ => false,
}
}


fn eval_fn_get_string_arg<'a>(
info: &'a expr::EvalFunctionInfo,
index: usize)
-> Result<&'a util::BigInt, bool>
-> Result<&'a expr::ValueString, bool>
{
match &info.args[index]
{
expr::Value::Integer(value) => Ok(value),
expr::Value::String(value) => Ok(value),
_ =>
{
info.report.error_span("expected integer argument", info.span);
info.report.error_span("expected string argument", &info.arg_spans[index]);
Err(true)
}
}
}


fn eval_fn_get_sized_bigint_arg<'a>(
info: &'a expr::EvalFunctionInfo,
fn eval_fn_get_bigint_arg(
info: &expr::EvalFunctionInfo,
index: usize)
-> Result<&'a util::BigInt, bool>
-> Result<util::BigInt, bool>
{
match &info.args[index]
match info.args[index].get_bigint()
{
Some(value) => Ok(value),
None =>
{
info.report.error_span("expected integer argument", &info.arg_spans[index]);
Err(true)
}
}
}


fn eval_fn_get_sized_bigint_arg(
info: &expr::EvalFunctionInfo,
index: usize)
-> Result<util::BigInt, bool>
{
match info.args[index].get_bigint()
{
expr::Value::Integer(value) =>
Some(value) =>
{
match value.size
{
Some(_) => Ok(value),
None =>
{
info.report.error_span("unsized integer argument", info.span);
info.report.error_span("unsized integer argument", &info.arg_spans[index]);
Err(true)
}
}
}
_ =>
None =>
{
info.report.error_span("expected integer argument", info.span);
info.report.error_span("expected integer argument", &info.arg_spans[index]);
Err(true)
}
}
Expand Down Expand Up @@ -1178,12 +1214,16 @@ impl State
"inchexstr" =>
{
State::eval_fn_check_arg_number(info, 1)?;
let bigint = State::eval_fn_get_bigint_arg(info, 0)?;
let filename = bigint.as_string();
if State::eval_fn_check_unknown_arg(info, 0, self.is_first_pass)
{
return Ok(expr::Value::make_integer(util::BigInt::new_from_str("")));
}

let value_string = State::eval_fn_get_string_arg(info, 0)?;
let new_filename = util::filename_navigate(
info.report.clone(),
&ctx.cur_filename,
&filename,
&value_string.utf8_contents,
&info.span)
.map_err(|_| true)?;

Expand Down Expand Up @@ -1337,9 +1377,9 @@ impl State
true,
info.args)?;

let (bigint, size) = match value
let (bigint, size) = match value.get_bigint()
{
expr::Value::Integer(bigint) =>
Some(bigint) =>
{
match bigint.size
{
Expand Down
60 changes: 37 additions & 23 deletions src/expr/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub struct EvalFunctionInfo<'a>
pub report: diagn::RcReport,
pub func: expr::Value,
pub args: Vec<expr::Value>,
pub arg_spans: Vec<diagn::Span>,
pub span: &'a diagn::Span,
}

Expand Down Expand Up @@ -201,9 +202,33 @@ impl expr::Expr

else
{
match (lhs_expr.eval(report.clone(), ctx, eval_var, eval_fn, eval_asm)?, rhs_expr.eval(report.clone(), ctx, eval_var, eval_fn, eval_asm)?)
let lhs = lhs_expr.eval(report.clone(), ctx, eval_var, eval_fn, eval_asm)?;
let rhs = rhs_expr.eval(report.clone(), ctx, eval_var, eval_fn, eval_asm)?;

match (&lhs, &rhs)
{
(expr::Value::Integer(ref lhs), expr::Value::Integer(ref rhs)) =>
(expr::Value::Bool(lhs), expr::Value::Bool(rhs)) =>
{
return match op
{
expr::BinaryOp::And => Ok(expr::Value::Bool(lhs & rhs)),
expr::BinaryOp::Or => Ok(expr::Value::Bool(lhs | rhs)),
expr::BinaryOp::Xor => Ok(expr::Value::Bool(lhs ^ rhs)),
expr::BinaryOp::Eq => Ok(expr::Value::Bool(lhs == rhs)),
expr::BinaryOp::Ne => Ok(expr::Value::Bool(lhs != rhs)),
_ => Err(report.error_span("invalid argument types to operator", &span))
}
}

_ => {}
}

let lhs_bigint = lhs.get_bigint();
let rhs_bigint = rhs.get_bigint();

match (lhs_bigint, rhs_bigint)
{
(Some(ref lhs), Some(ref rhs)) =>
{
match op
{
Expand Down Expand Up @@ -247,10 +272,6 @@ impl expr::Expr

expr::BinaryOp::Concat =>
{
// FIXME: wrongly evaluates lhs and rhs again, with possible duplicated side-effects
//let lhs_sliced = lhs_expr.eval_slice(report.clone(), ctx, eval_var, eval_fn)?;
//let rhs_sliced = rhs_expr.eval_slice(report.clone(), ctx, eval_var, eval_fn)?;

match (lhs.size, rhs.size)
{
(Some(lhs_width), Some(rhs_width)) => Ok(expr::Value::make_integer(lhs.concat((lhs_width, 0), &rhs, (rhs_width, 0)))),
Expand All @@ -263,19 +284,6 @@ impl expr::Expr
}
}

(expr::Value::Bool(lhs), expr::Value::Bool(rhs)) =>
{
match op
{
expr::BinaryOp::And => Ok(expr::Value::Bool(lhs & rhs)),
expr::BinaryOp::Or => Ok(expr::Value::Bool(lhs | rhs)),
expr::BinaryOp::Xor => Ok(expr::Value::Bool(lhs ^ rhs)),
expr::BinaryOp::Eq => Ok(expr::Value::Bool(lhs == rhs)),
expr::BinaryOp::Ne => Ok(expr::Value::Bool(lhs != rhs)),
_ => Err(report.error_span("invalid argument types to operator", &span))
}
}

_ => Err(report.error_span("invalid argument types to operator", &span))
}
}
Expand All @@ -293,10 +301,10 @@ impl expr::Expr

&expr::Expr::BitSlice(ref span, _, left, right, ref inner) =>
{
match inner.eval(report.clone(), ctx, eval_var, eval_fn, eval_asm)?
match inner.eval(report.clone(), ctx, eval_var, eval_fn, eval_asm)?.get_bigint()
{
expr::Value::Integer(ref x) => Ok(expr::Value::make_integer(x.slice(left, right))),
_ => Err(report.error_span("invalid argument type to slice", &span))
Some(ref x) => Ok(expr::Value::make_integer(x.slice(left, right))),
None => Err(report.error_span("invalid argument type to slice", &span))
}
}

Expand Down Expand Up @@ -324,14 +332,20 @@ impl expr::Expr
expr::Value::Function(_) =>
{
let mut args = Vec::new();
let mut arg_spans = Vec::new();
for expr in arg_exprs
{ args.push(expr.eval(report.clone(), ctx, eval_var, eval_fn, eval_asm)?); }
{
let arg = expr.eval(report.clone(), ctx, eval_var, eval_fn, eval_asm)?;
args.push(arg);
arg_spans.push(expr.span());
}

let info = EvalFunctionInfo
{
report: report.clone(),
func,
args,
arg_spans,
span,
};

Expand Down
21 changes: 21 additions & 0 deletions src/expr/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,23 @@ pub enum Expr
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Value
{
Unknown,
Void,
Integer(util::BigInt),
String(ValueString),
Bool(bool),
Function(String)
}


#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ValueString
{
pub utf8_contents: String,
pub encoding: String,
}


#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum UnaryOp
{
Expand Down Expand Up @@ -99,8 +109,19 @@ impl Value
{
match self
{
&Value::Unknown => Some(util::BigInt::from(0)),
&Value::Integer(ref bigint) => Some(bigint.clone()),
&Value::String(ref rc_string) => Some(rc_string.to_bigint()),
_ => None,
}
}
}


impl ValueString
{
pub fn to_bigint(&self) -> util::BigInt
{
util::BigInt::new_from_str(&self.utf8_contents)
}
}
1 change: 1 addition & 0 deletions src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod eval;

pub use self::expression::Expr;
pub use self::expression::Value;
pub use self::expression::ValueString;
pub use self::expression::UnaryOp;
pub use self::expression::BinaryOp;
pub use self::eval::EvalContext;
Expand Down
6 changes: 5 additions & 1 deletion src/expr/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,11 @@ impl<'a, 'parser> ExpressionParser<'a, 'parser>

let expr = expr::Expr::Literal(
tk_str.span.clone(),
expr::Value::Integer(util::BigInt::new_from_str(&string)));
expr::Value::String(expr::ValueString
{
utf8_contents: string,
encoding: "utf8".to_string(),
}));

Ok(expr)
}
Expand Down
Loading

0 comments on commit 4e1426c

Please sign in to comment.