diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index 87e0135bc0e117077ba4a62a7682c557ca1ae55d..a0b2c384c1a9684c8d213a3c57621a4769c4200a 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -1838,7 +1838,7 @@ pub struct CallExpression { #[derive(Debug, Clone, PartialEq, Eq)] pub enum Method { - // Builtin, accessible by programmer + // Builtin function, accessible by programmer Get, Put, Fires, @@ -1846,10 +1846,12 @@ pub enum Method { Length, Assert, Print, - // Builtin, not accessible by programmer + // Builtin function, not accessible by programmer SelectStart, // SelectStart(total_num_cases, total_num_ports) SelectRegisterCasePort, // SelectRegisterCasePort(case_index, port_index, port_id) SelectWait, // SelectWait() -> u32 + // Builtin component, + ComponentRandomU32, // User-defined UserFunction, UserComponent, @@ -1860,6 +1862,7 @@ impl Method { use Method::*; match self { Get | Put | Fires | Create | Length | Assert | Print => true, + ComponentRandomU32 => true, _ => false, } } diff --git a/src/protocol/eval/executor.rs b/src/protocol/eval/executor.rs index 2a77a1ebb0dcb357eb413cd626ea2b65a7abb639..ee304a55bd6a62074c4d83466a944773f3480ab6 100644 --- a/src/protocol/eval/executor.rs +++ b/src/protocol/eval/executor.rs @@ -755,11 +755,15 @@ impl Prompt { }, } }, + Method::ComponentRandomU32 => { + debug_assert_eq!(heap[expr.procedure].parameters.len(), cur_frame.expr_values.len()); + debug_assert_eq!(heap[cur_frame.position].as_new().expression, expr.this); + }, Method::UserComponent => { // This is actually handled by the evaluation // of the statement. debug_assert_eq!(heap[expr.procedure].parameters.len(), cur_frame.expr_values.len()); - debug_assert_eq!(heap[cur_frame.position].as_new().expression, expr.this) + debug_assert_eq!(heap[cur_frame.position].as_new().expression, expr.this); }, Method::UserFunction => { // Push a new frame. Note that all expressions have diff --git a/src/protocol/parser/mod.rs b/src/protocol/parser/mod.rs index 6d2a3281c144df2d3547c8bf2622498bdb2dd6a0..f79a81c83522d13a3b39043637b73fc234a79a45 100644 --- a/src/protocol/parser/mod.rs +++ b/src/protocol/parser/mod.rs @@ -296,8 +296,9 @@ impl Parser { use std::path::{Path, PathBuf}; use std::fs; - const FILES: [&'static str; 1] = [ + const FILES: [&'static str; 2] = [ "std.global.pdl", + "std.random.pdl", ]; // Determine base directory @@ -324,6 +325,7 @@ impl Parser { let mut first_file = true; for file in FILES { + file_path.clear(); file_path.push(path); file_path.push(file); diff --git a/src/protocol/parser/pass_definitions.rs b/src/protocol/parser/pass_definitions.rs index 7f9817270909d65c1cfc3c9fa702aef204e1506e..17b71cecd9f6981c66bf39a4775d6a55a9f83c6d 100644 --- a/src/protocol/parser/pass_definitions.rs +++ b/src/protocol/parser/pass_definitions.rs @@ -376,6 +376,7 @@ impl PassDefinitions { ("std.global", "length") => ProcedureSource::FuncLength, ("std.global", "assert") => ProcedureSource::FuncAssert, ("std.global", "print") => ProcedureSource::FuncPrint, + ("std.random", "random_u32") => ProcedureSource::CompRandomU32, _ => panic!( "compiler error: unknown builtin procedure '{}' in module '{}'", procedure_name, module_name @@ -825,10 +826,8 @@ impl PassDefinitions { if let Expression::Call(expression) = expression { // Allow both components and functions, as it makes more sense to // check their correct use in the validation and linking pass - if expression.method == Method::UserComponent || expression.method == Method::UserFunction { - call_id = expression.this; - valid = true; - } + call_id = expression.this; + valid = true; } if !valid { @@ -1658,7 +1657,8 @@ impl PassDefinitions { ProcedureSource::FuncLength => Method::Length, ProcedureSource::FuncAssert => Method::Assert, ProcedureSource::FuncPrint => Method::Print, - _ => todo!("other proc sources") + ProcedureSource::CompRandomU32 => Method::ComponentRandomU32, + _ => todo!("other procedure sources"), }; // Function call: consume the arguments diff --git a/src/protocol/parser/pass_validation_linking.rs b/src/protocol/parser/pass_validation_linking.rs index 19b463957c8388f64b0bd8eefdd1ea888cf44554..1a2b63139abc5a5e5174f9a7b0825ca370d506c7 100644 --- a/src/protocol/parser/pass_validation_linking.rs +++ b/src/protocol/parser/pass_validation_linking.rs @@ -1160,6 +1160,9 @@ impl Visitor for PassValidationLinking { Method::SelectStart | Method::SelectRegisterCasePort | Method::SelectWait => unreachable!(), // not usable by programmer directly + Method::ComponentRandomU32 => { + expecting_wrapping_new_stmt = true; + }, Method::UserFunction => {} Method::UserComponent => { expecting_wrapping_new_stmt = true; diff --git a/src/protocol/parser/type_table.rs b/src/protocol/parser/type_table.rs index 9c9be71adaba0cfb9393672e228c95f7f1aeec63..9737204e3d853d5e6f9c567ccf42c8b6b4ebdb69 100644 --- a/src/protocol/parser/type_table.rs +++ b/src/protocol/parser/type_table.rs @@ -2045,6 +2045,7 @@ impl TypeTable { // And now, we're actually, properly, done self.encountered_types.clear(); + self.size_alignment_stack.clear(); } /// Attempts to compute size/alignment for the provided type. Note that this diff --git a/src/runtime2/tests/mod.rs b/src/runtime2/tests/mod.rs index a316a1561c391dd2207cc46779f1acfeb2834c14..7900d9cfb8b1c8b8b355b75b695ce51d89678b8d 100644 --- a/src/runtime2/tests/mod.rs +++ b/src/runtime2/tests/mod.rs @@ -219,4 +219,21 @@ fn test_empty_select() { ").expect("compilation"); let rt = Runtime::new(3, false, pd); create_component(&rt, "", "constructor", no_args()); +} + +#[test] +fn test_random_u32_temporary_thingo() { + let pd = ProtocolDescription::parse(b" + primitive random_taker(in generator) { + sync { + auto a = get(generator); + } + } + + composite constructor() { + channel tx -> rx; + new random_u32(tx, 1, 100); + new random_taker(rx); + } + ").expect("compilation"); } \ No newline at end of file diff --git a/std/std.global.pdl b/std/std.global.pdl index 6ad5a3aeb2b8fb5597794a4d8ac15bd4462728b4..6691b79689ad5b304289b4c9feff3de3011bf515 100644 --- a/std/std.global.pdl +++ b/std/std.global.pdl @@ -1,10 +1,5 @@ #module std.global -// Note: parsing of token ranges and pragma needs to change. For now we insert -// spaces to work with the current system. Needs to be a system where the -// pragmas, "func" keywords (and similar keywords) indicate initial points to -// start parsing. - func get(in input) -> T { #builtin } func put(out output, T value) -> #type_void { #builtin } func fires(#type_portlike port) -> bool { #builtin } diff --git a/std/std.random.pdl b/std/std.random.pdl new file mode 100644 index 0000000000000000000000000000000000000000..6d4f24e232aec8ad705392a8fdeca70eff075b6c --- /dev/null +++ b/std/std.random.pdl @@ -0,0 +1,3 @@ +#module std.random + +primitive random_u32(out generator, u32 min, u32 max) { #builtin }