@@ -36,6 +36,7 @@ struct FsmBuilder {
3636#[ derive( Debug , Clone ) ]
3737struct EventBuilder {
3838 // Associates parameter's name with its type's name.
39+ name : String ,
3940 params : BTreeMap < String , String > ,
4041 senders : HashSet < PgId > ,
4142 receivers : HashSet < PgId > ,
@@ -172,6 +173,7 @@ impl ModelBuilder {
172173 self . event_indexes . get ( id) . cloned ( ) . unwrap_or_else ( || {
173174 let index = self . events . len ( ) ;
174175 self . events . push ( EventBuilder {
176+ name : id. to_string ( ) ,
175177 params : BTreeMap :: new ( ) ,
176178 index,
177179 senders : HashSet :: new ( ) ,
@@ -198,7 +200,7 @@ impl ModelBuilder {
198200 fn prebuild_processes ( & mut self , parser : & mut Parser ) -> anyhow:: Result < ( ) > {
199201 for ( id, fsm) in parser. process_list . iter_mut ( ) {
200202 let pg_id = self . fsm_builder ( id) . pg_id ;
201- self . prebuild_fsms ( pg_id, fsm, & parser. interner )
203+ self . prebuild_fsm ( pg_id, fsm, & parser. interner )
202204 . with_context ( || {
203205 format ! (
204206 "failed pre-processing of fsm {}" ,
@@ -208,10 +210,18 @@ impl ModelBuilder {
208210 )
209211 } ) ?;
210212 }
213+ for eb in & self . events {
214+ for ( param, t) in & eb. params {
215+ // Mark with empty string parameters without known type
216+ if t. is_empty ( ) {
217+ bail ! ( "param {param} of event {} needs type annotation" , eb. name) ;
218+ }
219+ }
220+ }
211221 Ok ( ( ) )
212222 }
213223
214- fn prebuild_fsms (
224+ fn prebuild_fsm (
215225 & mut self ,
216226 pg_id : PgId ,
217227 fmt : & mut Scxml ,
@@ -290,7 +300,9 @@ impl ModelBuilder {
290300 for param in params {
291301 // Update OMG_type value so that it contains its type for sure
292302 let builder = self . events . get_mut ( event_index) . expect ( "index must exist" ) ;
293- if let Some ( t) = builder. params . get ( & param. name ) {
303+ if let Some ( t) = builder. params . get ( & param. name )
304+ && !t. is_empty ( )
305+ {
294306 if let Some ( omg) = param. omg_type . as_ref ( ) {
295307 if t != omg {
296308 bail ! (
@@ -307,6 +319,10 @@ impl ModelBuilder {
307319 let _ = param. omg_type . insert ( t. clone ( ) ) ;
308320 let builder = self . events . get_mut ( event_index) . expect ( "index must exist" ) ;
309321 builder. params . insert ( param. name . clone ( ) , t) ;
322+ } else {
323+ // Mark with empty string parameters without known type
324+ let builder = self . events . get_mut ( event_index) . expect ( "index must exist" ) ;
325+ builder. params . insert ( param. name . clone ( ) , String :: new ( ) ) ;
310326 }
311327 }
312328 Ok ( ( ) )
@@ -399,7 +415,9 @@ impl ModelBuilder {
399415 ) )
400416 }
401417 }
402- boa_ast:: expression:: operator:: binary:: BinaryOp :: Bitwise ( _) => todo ! ( ) ,
418+ boa_ast:: expression:: operator:: binary:: BinaryOp :: Bitwise ( _) => {
419+ Err ( anyhow ! ( "bitwise operations not supported" ) )
420+ }
403421 boa_ast:: expression:: operator:: binary:: BinaryOp :: Relational ( _)
404422 | boa_ast:: expression:: operator:: binary:: BinaryOp :: Logical ( _) => {
405423 Ok ( String :: from ( "bool" ) )
@@ -409,6 +427,48 @@ impl ModelBuilder {
409427 ) ) ,
410428 }
411429 }
430+ boa_ast:: Expression :: Call ( call) => self . infer_type ( call. function ( ) , types, interner) ,
431+ boa_ast:: Expression :: PropertyAccess ( property_access) => match property_access {
432+ boa_ast:: expression:: access:: PropertyAccess :: Simple ( simple_property_access) => {
433+ if let & boa_ast:: Expression :: Identifier ( ident) = simple_property_access. target ( )
434+ {
435+ if ident. sym ( ) == interner. get ( "Math" ) . unwrap ( ) {
436+ match simple_property_access. field ( ) {
437+ boa_ast:: expression:: access:: PropertyAccessField :: Const (
438+ identifier,
439+ ) => {
440+ if identifier. sym ( ) == interner. get ( "floor" ) . unwrap ( ) {
441+ Ok ( String :: from ( "int32" ) )
442+ } else if identifier. sym ( ) == interner. get ( "random" ) . unwrap ( ) {
443+ Ok ( String :: from ( "float64" ) )
444+ } else {
445+ Err ( anyhow ! (
446+ "unknown expression '{expr:?}', unable to infer type"
447+ ) )
448+ }
449+ }
450+ boa_ast:: expression:: access:: PropertyAccessField :: Expr (
451+ _expression,
452+ ) => todo ! ( ) ,
453+ }
454+ } else {
455+ Err ( anyhow ! (
456+ "unknown expression '{expr:?}', unable to infer type"
457+ ) )
458+ }
459+ } else {
460+ Err ( anyhow ! (
461+ "unknown expression '{expr:?}', unable to infer type"
462+ ) )
463+ }
464+ }
465+ boa_ast:: expression:: access:: PropertyAccess :: Private ( _private_property_access) => {
466+ todo ! ( )
467+ }
468+ boa_ast:: expression:: access:: PropertyAccess :: Super ( _super_property_access) => {
469+ todo ! ( )
470+ }
471+ } ,
412472 _ => Err ( anyhow ! (
413473 "unknown expression '{expr:?}', unable to infer type"
414474 ) ) ,
@@ -1023,17 +1083,21 @@ impl ModelBuilder {
10231083 // Pass parameters. This could fail due to param content.
10241084 if !send_params. is_empty ( ) {
10251085 // Updates next location.
1026- next_loc = self . send_params (
1027- pg_id,
1028- target_id,
1029- & send_params,
1030- event_idx,
1031- next_loc,
1032- vars,
1033- origin,
1034- params,
1035- interner,
1036- ) ?;
1086+ next_loc = self
1087+ . send_params (
1088+ pg_id,
1089+ target_id,
1090+ & send_params,
1091+ event_idx,
1092+ next_loc,
1093+ vars,
1094+ origin,
1095+ params,
1096+ interner,
1097+ )
1098+ . with_context ( || {
1099+ anyhow ! ( "failed sending params for event {event}" )
1100+ } ) ?;
10371101 }
10381102 // Once sending event and args done, get to exit-point
10391103 self . cs
@@ -1183,6 +1247,12 @@ impl ModelBuilder {
11831247 interner : & Interner ,
11841248 ) -> Result < Location , anyhow:: Error > {
11851249 assert ! ( !params. is_empty( ) ) ;
1250+ // Check that no param is missing
1251+ for p in self . events [ event_idx] . params . keys ( ) {
1252+ if !params. iter ( ) . any ( |param| param. name == * p) {
1253+ bail ! ( "missing param {p}" ) ;
1254+ }
1255+ }
11861256 let mut exprs = Vec :: new ( ) ;
11871257 let mut scan_types = Vec :: new ( ) ;
11881258 for param in params {
@@ -1284,7 +1354,9 @@ impl ModelBuilder {
12841354 }
12851355 boa_ast:: Expression :: PropertyAccess ( prop_acc) => {
12861356 let expr = & boa_ast:: Expression :: PropertyAccess ( prop_acc. to_owned ( ) ) ;
1287- let ecma_obj = self . expression_prop_access ( expr, interner, vars, origin, params) ?;
1357+ let ecma_obj = self
1358+ . expression_prop_access ( expr, interner, vars, origin, params)
1359+ . context ( "failed building expression with property access" ) ?;
12881360 // WARN: If the EcmaObj is a primitive SCAN data, we return that.
12891361 // If it is a dictionary of properties, instead, we have no way to represent it properly as a SCAN type.
12901362 match ecma_obj {
@@ -1470,61 +1542,38 @@ impl ModelBuilder {
14701542 boa_ast:: Expression :: Identifier ( ident) => {
14711543 let ident = ident. to_interned_string ( interner) ;
14721544 match ident. as_str ( ) {
1473- "_event" => Ok ( EcmaObj :: Properties ( HashMap :: from_iter (
1474- [
1475- (
1476- String :: from ( "origin" ) ,
1477- EcmaObj :: PrimitiveData (
1478- Expression :: Var (
1479- origin
1480- . cloned ( )
1481- . ok_or ( anyhow ! ( "missing origin of _event" ) ) ?,
1482- Type :: Integer ,
1483- ) ,
1484- String :: from ( "int32" ) ,
1545+ "_event" => Ok ( EcmaObj :: Properties ( HashMap :: from_iter ( [
1546+ (
1547+ String :: from ( "origin" ) ,
1548+ EcmaObj :: PrimitiveData (
1549+ Expression :: Var (
1550+ origin. cloned ( ) . ok_or ( anyhow ! ( "missing origin of _event" ) ) ?,
1551+ Type :: Integer ,
14851552 ) ,
1553+ String :: from ( "int32" ) ,
14861554 ) ,
1487- (
1488- String :: from ( "data" ) ,
1489- EcmaObj :: Properties ( HashMap :: from_iter ( params. iter ( ) . map (
1490- |( n, ( v, t) ) | {
1491- (
1492- n. to_owned ( ) ,
1493- EcmaObj :: PrimitiveData (
1494- Expression :: Var (
1495- v. clone ( ) ,
1496- self . types
1497- . get ( t)
1498- . map ( |( _, t) | t. to_owned ( ) )
1499- . expect ( "type of data parameter" ) ,
1500- ) ,
1501- t. to_owned ( ) ,
1555+ ) ,
1556+ (
1557+ String :: from ( "data" ) ,
1558+ EcmaObj :: Properties ( HashMap :: from_iter ( params. iter ( ) . map (
1559+ |( n, ( v, t) ) | {
1560+ (
1561+ n. to_owned ( ) ,
1562+ EcmaObj :: PrimitiveData (
1563+ Expression :: Var (
1564+ v. clone ( ) ,
1565+ self . types
1566+ . get ( t)
1567+ . map ( |( _, t) | t. to_owned ( ) )
1568+ . expect ( "type of data parameter" ) ,
15021569 ) ,
1503- )
1504- } ,
1505- ) ) ) ,
1506- ) ,
1507- ]
1508- // WARN: This allows the non-conformant notation `_event.<PARAM>` in place of `_event.data.<PARAM>`
1509- // for compatibility with the format produced by AS2FM.
1510- // TODO: remove when not necessary anymore.
1511- . into_iter ( )
1512- . chain ( params. iter ( ) . map ( |( n, ( v, t) ) | {
1513- (
1514- n. to_owned ( ) ,
1515- EcmaObj :: PrimitiveData (
1516- Expression :: Var (
1517- v. clone ( ) ,
1518- self . types
1519- . get ( t)
1520- . map ( |( _, t) | t. to_owned ( ) )
1521- . expect ( "type of data parameter" ) ,
1522- ) ,
1523- t. to_owned ( ) ,
1524- ) ,
1525- )
1526- } ) ) ,
1527- ) ) ) ,
1570+ t. to_owned ( ) ,
1571+ ) ,
1572+ )
1573+ } ,
1574+ ) ) ) ,
1575+ ) ,
1576+ ] ) ) ) ,
15281577 ident => {
15291578 let ( var, type_name) = vars
15301579 . get ( ident)
0 commit comments