From 205cf21650f8811c6d3a3f10f8f02466fab5e863 Mon Sep 17 00:00:00 2001 From: Lennart Van Hirtum Date: Sun, 12 Jan 2025 02:30:43 +0100 Subject: [PATCH] Remove TypedValue --- src/codegen/system_verilog.rs | 4 +- src/dev_aid/lsp/hover_info.rs | 2 +- src/instantiation/concrete_typecheck.rs | 2 +- src/instantiation/execute.rs | 61 ++++++----- src/instantiation/mod.rs | 8 +- src/to_string.rs | 4 +- src/typing/template.rs | 8 +- src/value.rs | 130 ++++++++---------------- 8 files changed, 86 insertions(+), 133 deletions(-) diff --git a/src/codegen/system_verilog.rs b/src/codegen/system_verilog.rs index 189a796..c363ee1 100644 --- a/src/codegen/system_verilog.rs +++ b/src/codegen/system_verilog.rs @@ -327,8 +327,8 @@ impl<'g, 'out, Stream: std::fmt::Write> CodeGenerationContext<'g, 'out, Stream> ConcreteTemplateArg::Type(..) => { unreachable!("No extern module type arguments. Should have been caught by Lint") } - ConcreteTemplateArg::Value(typed_value, _) => { - typed_value.value.inline_constant_to_string() + ConcreteTemplateArg::Value(value, _) => { + value.inline_constant_to_string() } ConcreteTemplateArg::NotProvided => unreachable!("All args are known at codegen"), }; diff --git a/src/dev_aid/lsp/hover_info.rs b/src/dev_aid/lsp/hover_info.rs index d5fd520..4b33f9f 100644 --- a/src/dev_aid/lsp/hover_info.rs +++ b/src/dev_aid/lsp/hover_info.rs @@ -51,7 +51,7 @@ impl<'l> HoverCollector<'l> { if is_generative { let value_str = match &inst.generation_state[id] { SubModuleOrWire::SubModule(_) | SubModuleOrWire::Wire(_) => unreachable!(), - SubModuleOrWire::CompileTimeValue(v) => format!(" = {}", v.value), + SubModuleOrWire::CompileTimeValue(v) => format!(" = {}", v), SubModuleOrWire::Unnasigned => format!("never assigned to"), }; self.monospace(value_str); diff --git a/src/instantiation/concrete_typecheck.rs b/src/instantiation/concrete_typecheck.rs index ee8718c..61ab68a 100644 --- a/src/instantiation/concrete_typecheck.rs +++ b/src/instantiation/concrete_typecheck.rs @@ -177,7 +177,7 @@ fn try_to_attach_value_to_template_arg(template_wire_referernce: FlatID, found_v let ConcreteType::Value(v) = found_value else {return}; // We don't have a value to assign if let Some(template_id) = can_expression_be_value_inferred(submodule_link_info, template_wire_referernce) { if let ConcreteTemplateArg::NotProvided = &template_args[template_id] { - template_args[template_id] = ConcreteTemplateArg::Value(TypedValue::from_value(v.clone()), HowDoWeKnowTheTemplateArg::Inferred) + template_args[template_id] = ConcreteTemplateArg::Value(v.clone(), HowDoWeKnowTheTemplateArg::Inferred) } } } diff --git a/src/instantiation/execute.rs b/src/instantiation/execute.rs index 6e70bbc..47f3294 100644 --- a/src/instantiation/execute.rs +++ b/src/instantiation/execute.rs @@ -6,14 +6,15 @@ use std::ops::{Deref, Index, IndexMut}; -use crate::linker::{get_builtin_type, IsExtern}; +use crate::linker::IsExtern; use crate::prelude::*; +use crate::typing::concrete_type::BOOL_CONCRETE_TYPE; use crate::typing::template::{GlobalReference, HowDoWeKnowTheTemplateArg}; use num::BigInt; use crate::flattening::*; -use crate::value::{compute_binary_op, compute_unary_op, TypedValue, Value}; +use crate::value::{compute_binary_op, compute_unary_op, Value}; use crate::util::add_to_small_set; use crate::typing::{ @@ -76,12 +77,12 @@ impl<'fl> GenerationState<'fl> { *target = to_write; Ok(()) } - fn get_generation_value(&self, v: FlatID) -> ExecutionResult<&TypedValue> { + fn get_generation_value(&self, v: FlatID) -> ExecutionResult<&Value> { if let SubModuleOrWire::CompileTimeValue(vv) = &self.generation_state[v] { - if let Value::Unset | Value::Error = &vv.value { + if let Value::Unset | Value::Error = vv { Err(( self.span_of(v), - format!("This variable is set but it's {:?}!", vv.value), + format!("This variable is set but it's {:?}!", vv), )) } else { Ok(vv) @@ -129,18 +130,13 @@ impl<'fl> IndexMut for GenerationState<'fl> { } } -fn array_access(tv: &TypedValue, idx: &BigInt, span: BracketSpan) -> ExecutionResult { - let typ = tv.typ.down_array().clone(); - - let Value::Array(arr) = &tv.value else { +fn array_access<'v>(arr_val: &'v Value, idx: &BigInt, span: BracketSpan) -> ExecutionResult<&'v Value> { + let Value::Array(arr) = arr_val else { caught_by_typecheck!("Value must be an array") }; if let Some(elem) = usize::try_from(idx).ok().and_then(|idx| arr.get(idx)) { - Ok(TypedValue { - typ, - value: elem.clone(), - }) + Ok(elem) } else { Err(( span.outer_span(), @@ -188,13 +184,13 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { } /// TODO make builtins that depend on parameters - fn get_named_constant_value(&self, cst_ref: &GlobalReference) -> TypedValue { + fn get_named_constant_value(&self, cst_ref: &GlobalReference) -> Value { let linker_cst = &self.linker.constants[cst_ref.id]; if linker_cst.link_info.is_extern == IsExtern::Builtin { match linker_cst.link_info.name.as_str() { - "true" => TypedValue{value: Value::Bool(true), typ: ConcreteType::Named(get_builtin_type("bool"))}, - "false" => TypedValue{value: Value::Bool(false), typ: ConcreteType::Named(get_builtin_type("bool"))}, + "true" => Value::Bool(true), + "false" => Value::Bool(false), "__crash_compiler" => { cst_ref.get_total_span().debug(); panic!("__crash_compiler Intentional ICE. This is for debugging the compiler and LSP.") @@ -320,11 +316,11 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { else { unreachable!() }; - let mut new_val = std::mem::replace(&mut v_writable.value, Value::Error); + let mut new_val = std::mem::replace(v_writable, Value::Error); self.generation_state.write_gen_variable( &mut new_val, &target_wire_ref.path, - found_v.value, + found_v, )?; let SubModuleOrWire::CompileTimeValue(v_writable) = @@ -332,7 +328,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { else { unreachable!() }; - v_writable.value = new_val; + *v_writable = new_val; } RealWireRefRoot::Constant(_cst) => { caught_by_typecheck!("Cannot assign to constants"); @@ -356,7 +352,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { self.generation_state.write_gen_variable( initial_value, &target_wire_ref.path, - found_v.value, + found_v, )?; } } @@ -365,8 +361,8 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { fn compute_compile_time_wireref( &self, wire_ref: &WireReference, - ) -> ExecutionResult { - let mut work_on_value: TypedValue = match &wire_ref.root { + ) -> ExecutionResult { + let mut work_on_value: Value = match &wire_ref.root { &WireReferenceRoot::LocalDecl(decl_id, _span) => { self.generation_state.get_generation_value(decl_id)?.clone() } @@ -383,16 +379,16 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { &WireReferencePathElement::ArrayAccess { idx, bracket_span } => { let idx = self.generation_state.get_generation_integer(idx)?; - array_access(&work_on_value, idx, bracket_span)? + array_access(&work_on_value, idx, bracket_span)?.clone() } } } Ok(work_on_value) } - fn compute_compile_time(&mut self, expression: &Expression) -> ExecutionResult { + fn compute_compile_time(&mut self, expression: &Expression) -> ExecutionResult { Ok(match &expression.source { - ExpressionSource::WireRef(wire_ref) => self.compute_compile_time_wireref(wire_ref)?, + ExpressionSource::WireRef(wire_ref) => self.compute_compile_time_wireref(wire_ref)?.clone(), &ExpressionSource::UnaryOp { op, right } => { let right_val = self.generation_state.get_generation_value(right)?; compute_unary_op(op, right_val) @@ -404,7 +400,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { match op { BinaryOperator::Divide | BinaryOperator::Modulo => { use num::Zero; - if right_val.value.unwrap_integer().is_zero() { + if right_val.unwrap_integer().is_zero() { return Err(( expression.span, format!( @@ -419,20 +415,21 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { compute_binary_op(left_val, op, right_val) } - ExpressionSource::Constant(value) => TypedValue::from_value(value.clone()), + ExpressionSource::Constant(value) => value.clone(), }) } + fn alloc_wire_for_const( &mut self, - value: TypedValue, + value: Value, original_instruction: FlatID, domain: DomainID, ) -> WireID { self.wires.alloc(RealWire { - source: RealWireDataSource::Constant { value: value.value }, + typ : value.get_type_best_effort(&mut self.type_substitutor), + source: RealWireDataSource::Constant { value }, original_instruction, domain, - typ: value.typ, name: self.unique_name_producer.get_unique_name(""), specified_latency: CALCULATE_LATENCY_LATER, absolute_latency: CALCULATE_LATENCY_LATER, @@ -591,7 +588,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { self.template_args[template_id].unwrap_value().clone() } else { // Empty initial value - typ.get_initial_typed_val() + typ.get_initial_val() }; SubModuleOrWire::CompileTimeValue(value) } else { @@ -788,7 +785,7 @@ impl<'fl, 'l> InstantiationContext<'fl, 'l> { else { unreachable!() }; - *v = TypedValue::make_integer(current_val.clone()); + *v = Value::Integer(current_val.clone()); current_val += 1; self.instantiate_code_block(stm.loop_body)?; } diff --git a/src/instantiation/mod.rs b/src/instantiation/mod.rs index 765d2de..e797a72 100644 --- a/src/instantiation/mod.rs +++ b/src/instantiation/mod.rs @@ -18,7 +18,7 @@ use crate::{ config, errors::{CompileError, ErrorStore}, to_string::pretty_print_concrete_instance, - value::{TypedValue, Value}, + value::Value, }; use crate::typing::{ @@ -155,7 +155,7 @@ pub struct InstantiatedModule { pub enum SubModuleOrWire { SubModule(SubModuleID), Wire(WireID), - CompileTimeValue(TypedValue), + CompileTimeValue(Value), // Variable doesn't exist yet Unnasigned, } @@ -169,7 +169,7 @@ impl SubModuleOrWire { *result } #[track_caller] - pub fn unwrap_generation_value(&self) -> &TypedValue { + pub fn unwrap_generation_value(&self) -> &Value { let Self::CompileTimeValue(result) = self else { unreachable!("SubModuleOrWire::unwrap_generation_value failed! Is {self:?} instead") }; @@ -192,7 +192,7 @@ pub enum RealWireRefRoot { preamble: Vec, }, Generative(FlatID), - Constant(TypedValue), + Constant(Value), } #[derive(Debug)] diff --git a/src/to_string.rs b/src/to_string.rs index 3f33184..dd4e892 100644 --- a/src/to_string.rs +++ b/src/to_string.rs @@ -242,8 +242,8 @@ where TypVec: Index { ConcreteTemplateArg::Type(concrete_type, how_do_we_know_the_template_arg) => { write!(result, "type {} /* {} */,\n", concrete_type.to_string(linker_types), how_do_we_know_the_template_arg.to_str()).unwrap(); } - ConcreteTemplateArg::Value(typed_value, how_do_we_know_the_template_arg) => { - write!(result, "{} /* {} */,\n", typed_value.value.to_string(), how_do_we_know_the_template_arg.to_str()).unwrap(); + ConcreteTemplateArg::Value(value, how_do_we_know_the_template_arg) => { + write!(result, "{} /* {} */,\n", value.to_string(), how_do_we_know_the_template_arg.to_str()).unwrap(); } ConcreteTemplateArg::NotProvided => { write!(result, "/* Could not infer */\n").unwrap(); diff --git a/src/typing/template.rs b/src/typing/template.rs index b8747f8..ec62e5a 100644 --- a/src/typing/template.rs +++ b/src/typing/template.rs @@ -1,7 +1,7 @@ -use crate::prelude::*; +use crate::{prelude::*, value::Value}; use super::{abstract_type::AbstractType, concrete_type::ConcreteType}; -use crate::{flattening::WrittenType, value::TypedValue}; +use crate::flattening::WrittenType; #[derive(Debug)] pub struct GlobalReference { @@ -110,7 +110,7 @@ impl HowDoWeKnowTheTemplateArg { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ConcreteTemplateArg { Type(ConcreteType, HowDoWeKnowTheTemplateArg), - Value(TypedValue, HowDoWeKnowTheTemplateArg), + Value(Value, HowDoWeKnowTheTemplateArg), NotProvided, } @@ -121,7 +121,7 @@ impl ConcreteTemplateArg { t } #[track_caller] - pub fn unwrap_value(&self) -> &TypedValue { + pub fn unwrap_value(&self) -> &Value { let Self::Value(v, _) = self else {unreachable!()}; v } diff --git a/src/value.rs b/src/value.rs index 8e4ba18..b0db252 100644 --- a/src/value.rs +++ b/src/value.rs @@ -4,9 +4,10 @@ use num::BigInt; use crate::flattening::{BinaryOperator, UnaryOperator}; -use crate::typing:: - concrete_type::{ConcreteType, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE} -; +use crate::typing::{ + concrete_type::{ConcreteType, BOOL_CONCRETE_TYPE, INT_CONCRETE_TYPE}, + type_inference::{ConcreteTypeVariableIDMarker, TypeSubstitutor} +}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Value { @@ -18,18 +19,26 @@ pub enum Value { } impl Value { - pub fn get_concrete_type_of_constant(&self) -> ConcreteType { + /// Traverses the Value, to create a best-effort [ConcreteType] for it. + /// So '1' becomes [INT_CONCRETE_TYPE], + /// but `Value::Array([])` becomes `ConcreteType::Array(ConcreteType::Unknown)` + /// + /// Panics when arrays contain mutually incompatible types + pub fn get_type_best_effort(&self, type_substitutor: &mut TypeSubstitutor) -> ConcreteType { match self { Value::Bool(_) => BOOL_CONCRETE_TYPE, Value::Integer(_) => INT_CONCRETE_TYPE, - Value::Array(_b) => { - unreachable!("Can't express arrays as constants (yet?)"); - /*let content_typ = if let Some(b_first) = b.first() { - b_first.get_type() - } else { - Type::Invalid + Value::Array(arr) => { + let mut arr_iter = arr.iter(); + let Some(fst) = arr_iter.next() else {return ConcreteType::Unknown(type_substitutor.alloc())}; + let typ = fst.get_type_best_effort(type_substitutor); + + for other in arr_iter { + // Assert the types are correct + assert!(other.is_of_type(&typ)); } - Type::Array(Box::new((content_typ, b.len())))*/ + + ConcreteType::Array(Box::new((typ, ConcreteType::Value(Value::Integer(arr.len().into()))))) } Value::Unset | Value::Error => unreachable!(), } @@ -82,10 +91,10 @@ impl Value { } } -pub fn compute_unary_op(op: UnaryOperator, v: &TypedValue) -> TypedValue { - if v.value == Value::Error { +pub fn compute_unary_op(op: UnaryOperator, v: &Value) -> Value { + if *v == Value::Error { unreachable!("unary op on Value::Error!") - //return TypedValue{typ : , value : Value::Error} + //return Value::Error } match op { UnaryOperator::Or => { @@ -98,11 +107,10 @@ pub fn compute_unary_op(op: UnaryOperator, v: &TypedValue) -> TypedValue { todo!("Array Values") } UnaryOperator::Not => { - assert_eq!(v.typ, BOOL_CONCRETE_TYPE); - let Value::Bool(b) = &v.value else { + let Value::Bool(b) = v else { unreachable!("Only not bool supported, should be caught by abstract typecheck") }; - TypedValue::make_bool(!*b) + Value::Bool(!*b) } UnaryOperator::Sum => { todo!("Array Values") @@ -111,96 +119,51 @@ pub fn compute_unary_op(op: UnaryOperator, v: &TypedValue) -> TypedValue { todo!("Array Values") } UnaryOperator::Negate => { - assert_eq!(v.typ, INT_CONCRETE_TYPE); - let Value::Integer(v) = &v.value else { + let Value::Integer(v) = v else { panic!() }; - TypedValue::make_integer(-v) + Value::Integer(-v) } } } -pub fn compute_binary_op(left: &TypedValue, op: BinaryOperator, right: &TypedValue) -> TypedValue { - if left.value == Value::Error || right.value == Value::Error { +pub fn compute_binary_op(left: &Value, op: BinaryOperator, right: &Value) -> Value { + if *left == Value::Error || *right == Value::Error { unreachable!("binary op on Value::Error!") //return Value::Error } - let lv = &left.value; - let rv = &right.value; match op { - BinaryOperator::Equals => TypedValue::make_bool(lv == rv), - BinaryOperator::NotEquals => TypedValue::make_bool(lv != rv), + BinaryOperator::Equals => Value::Bool(left == right), + BinaryOperator::NotEquals => Value::Bool(left != right), BinaryOperator::GreaterEq => { - TypedValue::make_bool(lv.unwrap_integer() >= rv.unwrap_integer()) + Value::Bool(left.unwrap_integer() >= right.unwrap_integer()) } - BinaryOperator::Greater => TypedValue::make_bool(lv.unwrap_integer() > rv.unwrap_integer()), + BinaryOperator::Greater => Value::Bool(left.unwrap_integer() > right.unwrap_integer()), BinaryOperator::LesserEq => { - TypedValue::make_bool(lv.unwrap_integer() <= rv.unwrap_integer()) + Value::Bool(left.unwrap_integer() <= right.unwrap_integer()) } - BinaryOperator::Lesser => TypedValue::make_bool(lv.unwrap_integer() < rv.unwrap_integer()), - BinaryOperator::Add => TypedValue::make_integer(lv.unwrap_integer() + rv.unwrap_integer()), + BinaryOperator::Lesser => Value::Bool(left.unwrap_integer() < right.unwrap_integer()), + BinaryOperator::Add => Value::Integer(left.unwrap_integer() + right.unwrap_integer()), BinaryOperator::Subtract => { - TypedValue::make_integer(lv.unwrap_integer() - rv.unwrap_integer()) + Value::Integer(left.unwrap_integer() - right.unwrap_integer()) } BinaryOperator::Multiply => { - TypedValue::make_integer(lv.unwrap_integer() * rv.unwrap_integer()) + Value::Integer(left.unwrap_integer() * right.unwrap_integer()) } BinaryOperator::Divide => { - TypedValue::make_integer(lv.unwrap_integer() / rv.unwrap_integer()) + Value::Integer(left.unwrap_integer() / right.unwrap_integer()) } BinaryOperator::Modulo => { - TypedValue::make_integer(lv.unwrap_integer() % rv.unwrap_integer()) + Value::Integer(left.unwrap_integer() % right.unwrap_integer()) } - BinaryOperator::And => TypedValue::make_bool(lv.unwrap_bool() & rv.unwrap_bool()), - BinaryOperator::Or => TypedValue::make_bool(lv.unwrap_bool() & rv.unwrap_bool()), - BinaryOperator::Xor => TypedValue::make_bool(lv.unwrap_bool() & rv.unwrap_bool()), + BinaryOperator::And => Value::Bool(left.unwrap_bool() & right.unwrap_bool()), + BinaryOperator::Or => Value::Bool(left.unwrap_bool() & right.unwrap_bool()), + BinaryOperator::Xor => Value::Bool(left.unwrap_bool() & right.unwrap_bool()), //BinaryOperator::ShiftLeft => todo!(), // Still a bit iffy about shift operator inclusion //BinaryOperator::ShiftRight => todo!() } } -/// A value with an attached [ConcreteType]. -/// -/// TODO: Because we now have Hindley-Milner type inference, the need for adding types to values seems to have gone away -/// IE, the reason we added types in the first place was because we couldn't figure out the type of an empty array, but with HM that's no problem -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TypedValue { - pub value: Value, - pub typ: ConcreteType, -} - -impl TypedValue { - pub fn make_bool(b: bool) -> Self { - Self { - typ: BOOL_CONCRETE_TYPE, - value: Value::Bool(b), - } - } - pub fn make_integer(i: BigInt) -> Self { - Self { - typ: INT_CONCRETE_TYPE, - value: Value::Integer(i), - } - } - /// panics if the value can't be typed. - pub fn from_value(value: Value) -> Self { - Self { - typ: value.get_concrete_type_of_constant(), - value, - } - } - - #[track_caller] - pub fn unwrap_integer(&self) -> &BigInt { - self.value.unwrap_integer() - } - - #[track_caller] - pub fn unwrap_bool(&self) -> bool { - self.value.unwrap_bool() - } -} - impl ConcreteType { pub fn get_initial_val(&self) -> Value { match self { @@ -218,11 +181,4 @@ impl ConcreteType { ConcreteType::Value(_) | ConcreteType::Unknown(_) => unreachable!(), } } - - pub fn get_initial_typed_val(self) -> TypedValue { - TypedValue { - value: self.get_initial_val(), - typ : self, - } - } }