Skip to content

Commit

Permalink
Resolve i32 constants via DefMap
Browse files Browse the repository at this point in the history
  • Loading branch information
DCNick3 committed Oct 23, 2023
1 parent 6254e98 commit 684d7ec
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 24 deletions.
23 changes: 20 additions & 3 deletions shin-asm/src/compile/constexpr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::compile::diagnostics::{Diagnostic, Span};
use crate::compile::hir::Expr;
use crate::compile::{hir, make_diagnostic};
use crate::syntax::ast;
use crate::syntax::ast::UnaryOp;
use either::Either;
use rustc_hash::FxHashMap;

Expand All @@ -18,7 +19,7 @@ impl ConstexprValue {
Self(None)
}

fn unwrap(self) -> Option<i32> {
pub fn unwrap(self) -> Option<i32> {
self.0
}
}
Expand Down Expand Up @@ -98,8 +99,24 @@ fn evaluate(ctx: &mut EvaluateContext, expr: hir::ExprId) -> ConstexprValue {
)),
Expr::Array(_) => ctx.error(type_mismatch(Either::Left(expr), "int or float", "array")),
Expr::Mapping(_) => ctx.error(type_mismatch(Either::Left(expr), "int or float", "mapping")),
Expr::UnaryOp { .. } => {
todo!()
Expr::UnaryOp { expr: val, op } => {
let Some(val) = evaluate(ctx, val).unwrap() else {
return ConstexprValue::dummy();
};

let result = match op {
UnaryOp::Negate => val.checked_neg(),
UnaryOp::LogigalNot => Some(if val == 0 { 1 } else { 0 }),
UnaryOp::BitwiseNot => Some(!val),
};

match result {
Some(result) => ConstexprValue::constant(result),
None => ctx.error(make_diagnostic!(
Either::Left(expr),
"Overflow in constant expression"
)),
}
}
Expr::BinaryOp { lhs, rhs, op } => {
let lhs = evaluate(ctx, lhs);
Expand Down
1 change: 1 addition & 0 deletions shin-asm/src/compile/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct Jar(
def_map::DefMap,
def_map::DefMap_global_register,
def_map::DefMap_local_register,
def_map::DefMap_resolve_item,
def_map::build_def_map,
hir::HirBlockBodies,
hir::HirBlockBodies_get_block,
Expand Down
7 changes: 6 additions & 1 deletion shin-asm/src/compile/def_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod collect;
mod items;
mod registers;

pub use items::ResolvedItems;
pub use items::{DefValue, ResolvedItems};
pub use registers::{LocalRegisters, ResolvedGlobalRegisters};
use std::borrow::Cow;

Expand Down Expand Up @@ -111,6 +111,11 @@ impl DefMap {
self.global_register(db, name)
}

#[salsa::tracked]
pub fn resolve_item(self, db: &dyn Db, name: Name) -> Option<DefValue> {
self.items(db).get(&name).cloned()
}

pub fn debug_dump(self, db: &dyn Db) -> String {
use std::fmt::Write as _;

Expand Down
2 changes: 1 addition & 1 deletion shin-asm/src/compile/hir/lower/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ mod tests {
───╯
Error: Expected either a number or a register, found a name reference
Error: Could not find the definition of `aslk`
╭─[test.sal:1:10]
1 │ zero $v0 aslk as
Expand Down
59 changes: 49 additions & 10 deletions shin-asm/src/compile/hir/lower/elements/numbers.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,66 @@
use super::prelude::*;
use crate::compile::{constexpr::ConstexprValue, def_map::DefValue};
use shin_core::format::scenario::instruction_elements::{NumberSpec, UntypedNumberSpec};

fn try_lit_i32(block: &HirBlockBody, expr: ExprId) -> Option<i32> {
fn try_lit_i32(
diagnostics: &mut HirDiagnosticCollectorWithBlock,
resolve_ctx: &ResolveContext,
block: &HirBlockBody,
expr: ExprId,
) -> Option<ConstexprValue> {
match block.exprs[expr] {
hir::Expr::Literal(hir::Literal::IntNumber(lit)) => Some(lit),
hir::Expr::Literal(hir::Literal::RationalNumber(lit)) => Some(lit.into_raw()),
hir::Expr::Literal(hir::Literal::IntNumber(lit)) => Some(ConstexprValue::constant(lit)),
hir::Expr::Literal(hir::Literal::RationalNumber(lit)) => {
Some(ConstexprValue::constant(lit.into_raw()))
}
hir::Expr::UnaryOp {
op: ast::UnaryOp::Negate,
expr,
} => match block.exprs[expr] {
hir::Expr::Literal(hir::Literal::IntNumber(lit)) => Some(-lit),
hir::Expr::Literal(hir::Literal::RationalNumber(lit)) => Some(-lit.into_raw()),
hir::Expr::Literal(hir::Literal::IntNumber(lit)) => {
Some(ConstexprValue::constant(-lit))
}
hir::Expr::Literal(hir::Literal::RationalNumber(lit)) => {
Some(ConstexprValue::constant(-lit.into_raw()))
}
_ => None,
},
hir::Expr::NameRef(ref name) => match resolve_ctx.resolve_item(name) {
None => {
diagnostics.emit(
expr.into(),
format!("Could not find the definition of `{}`", name),
);
Some(ConstexprValue::dummy())
}
Some(DefValue::Block(_)) => {
diagnostics.emit(
expr.into(),
format!("Expected a number, found a code reference"),
);
Some(ConstexprValue::dummy())
}
Some(DefValue::Value(value)) => Some(value),
},
_ => None,
}
}

impl FromHirExpr for i32 {
fn from_hir_expr(
diagnostics: &mut HirDiagnosticCollectorWithBlock,
_resolve_ctx: &ResolveContext,
resolve_ctx: &ResolveContext,
block: &HirBlockBody,
expr: ExprId,
) -> Option<Self> {
let lit = try_lit_i32(block, expr);
let lit = try_lit_i32(diagnostics, resolve_ctx, block, expr);

let Some(lit) = lit else {
diagnostics.emit(expr.into(), "Expected a number".into());
return None;
};

Some(lit)
lit.unwrap()
}
}

Expand All @@ -45,8 +74,8 @@ impl FromHirExpr for NumberSpec {
expr: ExprId,
) -> Option<Self> {
let untyped = (|| {
if let Some(lit) = try_lit_i32(block, expr) {
Some(UntypedNumberSpec::Constant(lit))
if let Some(lit) = try_lit_i32(diagnostics, resolve_ctx, block, expr) {
Some(UntypedNumberSpec::Constant(lit.unwrap()?))
} else if let hir::Expr::RegisterRef(register) = &block.exprs[expr] {
let register = resolve_ctx.resolve_register(register.as_ref()?)?;

Expand All @@ -70,13 +99,23 @@ impl FromHirExpr for NumberSpec {
#[cfg(test)]
mod tests {
use super::super::check_from_hir_ok;
use indoc::indoc;
use shin_core::format::scenario::instruction_elements::{NumberSpec, UntypedNumberSpec};

// TODO: test diagnostics

#[test]
fn i32_from_hir() {
check_from_hir_ok::<i32>("HELLO 1, -2, 10.0", &[1, -2, 10_000]);
check_from_hir_ok::<i32>(
indoc! {r"
def ALIAS = -2
def ALIAS_RATIONAL = 10.0
HELLO 1, ALIAS, ALIAS_RATIONAL
"},
&[1, -2, 10_000],
);
}

#[test]
Expand Down
11 changes: 6 additions & 5 deletions shin-asm/src/compile/hir/lower/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,26 @@ mod tests {
check_from_hir(
indoc! {"
def $BIBA = $a0
def FORTY_TWO = 42
BLOCK1:
abs $v0, 42
zero $BIBA
BLOCK2:
not16 $v1, $v0
not16 $v1, FORTY_TWO
abs $a1, $BIBA
"},
expect![[r#"
block Block { item_index: ItemIndex(1), block_index: BlockIndex(0) }:
block Block { item_index: ItemIndex(2), block_index: BlockIndex(0) }:
instructions:
uo(UnaryOperation { ty: Abs, destination: $v0, source: 42 })
uo(UnaryOperation { ty: Zero, destination: $a0, source: 0 })
code addresses:
block Block { item_index: ItemIndex(1), block_index: BlockIndex(1) }:
block Block { item_index: ItemIndex(2), block_index: BlockIndex(1) }:
instructions:
uo(UnaryOperation { ty: Not16, destination: $v1, source: $v0 })
uo(UnaryOperation { ty: Not16, destination: $v1, source: 42 })
uo(UnaryOperation { ty: Abs, destination: $a1, source: $a0 })
code addresses:
Expand Down Expand Up @@ -163,7 +164,7 @@ mod tests {
───╯
Error: Expected either a number or a register, found a name reference
Error: Could not find the definition of `z`
╭─[test.sal:7:19]
7 │ not16 $KEKAS, z
Expand Down
14 changes: 10 additions & 4 deletions shin-asm/src/compile/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::compile::def_map::{RegisterName, ResolveKind};
use crate::compile::def_map::{DefValue, Name, RegisterName, ResolveKind};
use crate::{
compile::{Db, DefMap},
syntax::ast::{self},
Expand Down Expand Up @@ -50,7 +50,13 @@ impl<'a> ResolveContext<'a> {
}
}

// pub fn resolve_definition(&self, _name: &Name) -> Option<DefRef> {
// todo!()
// }
pub fn resolve_item(&self, name: &Name) -> Option<DefValue> {
match self.inner {
ResolveContextInner::Empty => None,
ResolveContextInner::Real {
def_map,
resolve_kind: _,
} => def_map.resolve_item(self.db, name.clone()),
}
}
}

0 comments on commit 684d7ec

Please sign in to comment.