Skip to content

Commit 0251bc6

Browse files
committed
Fixes lookup problem of constants in a package.
1 parent b0b6589 commit 0251bc6

File tree

11 files changed

+180
-129
lines changed

11 files changed

+180
-129
lines changed

src/core/env.ml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -818,9 +818,8 @@ type expression_symbol =
818818
| ExprEnum of (path * Loc.t * int)
819819
| ExprNotFound
820820

821-
let lookupExpressionSymbol (env : env) (name : string) (loc : Loc.t) (in_constant_context : bool) : expression_symbol =
822-
let name_path : path = { id = name; n = None; loc } in
823-
let results = lookupPath env name_path in
821+
let lookupExpressionSymbol (env : env) (path : path) (in_constant_context : bool) : expression_symbol =
822+
let results = lookupPath env path in
824823
if in_constant_context then
825824
(* In constant context: constants first, then enums, then types *)
826825
match findVar results with

src/core/inference.ml

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@ and exp ?(in_constant_context = false) (env : env) (e : Syntax.exp) : env * exp
373373
env, { e = EString value; t; loc }
374374
| { e = SEGroup e; _ } -> exp ~in_constant_context env e
375375
| { e = SEId name; loc } when not (String.equal (String.capitalize_ascii name) name) -> (
376-
match Env.lookupExpressionSymbol env name loc in_constant_context with
376+
let name_path : path = { id = name; n = None; loc } in
377+
match Env.lookupExpressionSymbol env name_path in_constant_context with
377378
| ExprVariable var ->
378379
let t = var.t in
379380
let e =
@@ -503,41 +504,61 @@ and exp ?(in_constant_context = false) (env : env) (e : Syntax.exp) : env * exp
503504
let t = applyFunction e.loc args_t ret [ e ] in
504505
env, { e = EUnOp (op, e); t; loc }
505506
| { e = SEMember (e1, m); loc } -> (
506-
(* First, try to interpret this as an enum reference if e1 is an SEId *)
507+
(* First, try to interpret this as an enum reference if e1 is an SEId or SEEnum *)
507508
match e1 with
508-
| { e = SEId module_name; _ } -> (
509-
(* Try to lookup as enum: module_name.m *)
510-
let enum_path = Syntax.{ id = m; n = Some module_name; loc } in
511-
try
512-
let type_path, tloc, index = Env.lookEnum env enum_path loc in
513-
let t = C.path_t tloc type_path in
514-
env, { e = EInt index; t; loc }
515-
with
516-
| _ -> (
517-
(* If enum lookup fails, fall back to normal member access *)
518-
let env, e1 = exp ~in_constant_context env e1 in
519-
match (unlink e1.t).tx with
520-
| TEId path -> (
521-
match Env.lookType env path loc with
522-
| { path; descr = Record members; _ } -> (
523-
match Map.find m members with
524-
| None -> Error.raiseError ("The field '" ^ m ^ "' is not part of the type '" ^ pathString path ^ "'") loc
525-
| Some { t; _ } ->
526-
let t = refreshConstness t in
527-
(* if the type is a builtin (a value) do not unify the constness *)
528-
let () =
529-
if (not in_constant_context) && not (Env.isBuiltinType t) then
530-
unifyConstness t e1.t
531-
in
532-
env, { e = EMember (e1, m); t; loc })
533-
| _ ->
534-
let t = Pla.print (Typed.print_type_ e1.t) in
535-
let e = Pla.print (Typed.print_exp e1) in
536-
Error.raiseError ("The expression '" ^ e ^ "' of type '" ^ t ^ "' does not have a member '" ^ m ^ "'.") loc)
537-
| _ ->
538-
let t = Pla.print (Typed.print_type_ e1.t) in
539-
let e = Pla.print (Typed.print_exp e1) in
540-
Error.raiseError ("The expression '" ^ e ^ "' of type '" ^ t ^ "' does not have a member '" ^ m ^ "'.") loc))
509+
| { e = SEId module_name; _ } when String.equal (String.capitalize_ascii module_name) module_name -> (
510+
(* First check if this is a module name - try module-qualified access *)
511+
let const_path = Syntax.{ id = m; n = Some module_name; loc } in
512+
let results = Env.lookupPath env const_path in
513+
match results with
514+
| _ :: _ -> (
515+
(* Found something in module - check what it is *)
516+
match Env.findVar results with
517+
| Some var when var.kind = Const ->
518+
let t = var.t in
519+
env, { e = EConst const_path; t; loc }
520+
| Some var ->
521+
Error.raiseError
522+
("Found '"
523+
^ module_name
524+
^ "."
525+
^ m
526+
^ "' but it's not a constant (it's a "
527+
^ (match var.kind with
528+
| Val -> "variable"
529+
| Mem _ -> "memory"
530+
| Inst -> "instance"
531+
| Const -> "constant")
532+
^ ")")
533+
loc
534+
| None -> (
535+
(* Check for function or enum *)
536+
match Env.findFunction results with
537+
| Some _ ->
538+
Error.raiseError
539+
("'"
540+
^ module_name
541+
^ "."
542+
^ m
543+
^ "' is a function, not a constant. Use function call syntax: "
544+
^ module_name
545+
^ "."
546+
^ m
547+
^ "(args)")
548+
loc
549+
| None -> (
550+
match Env.findEnum results with
551+
| Some (type_path, tloc, index) ->
552+
let t = C.path_t tloc type_path in
553+
env, { e = EInt index; t; loc }
554+
| None ->
555+
Error.raiseError ("Found '" ^ module_name ^ "." ^ m ^ "' but it's not a constant, function, or enum") loc)
556+
))
557+
| [] ->
558+
(* Module not found - check if it's an actual module name or just not found *)
559+
Error.raiseError
560+
("Module '" ^ module_name ^ "' not found. Check that the module is included or spelled correctly")
561+
loc)
541562
| _ -> (
542563
(* For non-SEId expressions, use normal member access *)
543564
let env, e1 = exp ~in_constant_context env e1 in
@@ -563,13 +584,10 @@ and exp ?(in_constant_context = false) (env : env) (e : Syntax.exp) : env * exp
563584
let t = Pla.print (Typed.print_type_ e1.t) in
564585
let e = Pla.print (Typed.print_exp e1) in
565586
Error.raiseError ("The expression '" ^ e ^ "' of type '" ^ t ^ "' does not have a member '" ^ m ^ "'.") loc))
566-
| { e = SEEnum path; loc } ->
567-
let type_path, tloc, index = Env.lookEnum env path loc in
568-
let t = C.path_t tloc type_path in
569-
env, { e = EInt index; t; loc }
570587
| { e = SEId id; loc } -> (
571588
(* This case handles uppercase identifiers (enum constructors) *)
572-
match Env.lookupExpressionSymbol env id loc in_constant_context with
589+
let id_path : path = { id; n = None; loc } in
590+
match Env.lookupExpressionSymbol env id_path in_constant_context with
573591
| ExprEnum (type_path, tloc, index) ->
574592
let t = C.path_t tloc type_path in
575593
env, { e = EInt index; t; loc }
@@ -755,7 +773,7 @@ let makeIterWhile (env : env) name id_loc value body loc =
755773
{ s = SStmtBlock [ decl; while_s ]; loc }
756774

757775

758-
let makeIfOfMatch e cases =
776+
let makeIfOfMatch env e cases =
759777
let rec makeComparison (e : Syntax.exp) (p : Syntax.pattern) =
760778
let makeEq e1 e2 = Syntax.{ e = SEOp ("==", e1, e2); loc = e1.loc } in
761779
let makeAnd e1 e2 = Syntax.{ e = SEOp ("&&", e1, e2); loc = e1.loc } in
@@ -789,7 +807,17 @@ let makeIfOfMatch e cases =
789807
| _, { p = SPReal f; loc } -> makeEq e Syntax.{ e = SEReal f; loc }
790808
| _, { p = SPFixed f; loc } -> makeEq e Syntax.{ e = SEFixed f; loc }
791809
| _, { p = SPString s; loc } -> makeEq e Syntax.{ e = SEString s; loc }
792-
| _, { p = SPEnum p; loc } -> makeEq e Syntax.{ e = SEEnum p; loc }
810+
| _, { p = SPId id; loc } -> (
811+
(* Handle enum constructor and constant patterns *)
812+
let id_path : path = { id; n = None; loc } in
813+
match Env.lookupExpressionSymbol env id_path false with
814+
| ExprEnum (_, _, _) ->
815+
(* Enum constructor: compare with the enum value itself *)
816+
makeEq e Syntax.{ e = SEId id; loc }
817+
| ExprVariable var when var.kind = Const ->
818+
(* Constant: create a constant reference for comparison *)
819+
makeEq e Syntax.{ e = SEId id; loc }
820+
| _ -> Error.raiseError ("Pattern '" ^ id ^ "' is not a valid enum constructor or constant") loc)
793821
in
794822
let if_stmt =
795823
CCList.fold_right
@@ -855,7 +883,7 @@ let rec stmt (env : env) (return : type_) (s : Syntax.stmt) : env * stmt list =
855883
let while_s = makeIterWhile env name id_loc value body loc in
856884
stmt env return while_s
857885
| { s = SStmtMatch { e; cases }; _ } ->
858-
let if_stmt = makeIfOfMatch e cases in
886+
let if_stmt = makeIfOfMatch env e cases in
859887
stmt env return if_stmt
860888

861889

src/driver/loader.ml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,17 @@ module Dependencies = struct
7171
| SEOp (_, e1, e2) -> exp (exp set e1) e2
7272
| SEIf { cond; then_; else_ } -> exp (exp (exp set cond) then_) else_
7373
| SETuple elems -> list exp set elems
74-
| SEMember (e, _) -> exp set e
74+
| SEMember (e, member) -> (
75+
(* Check if this is module-qualified access: Module.member *)
76+
match e with
77+
| { e = SEId module_name; loc } when String.equal (String.capitalize_ascii module_name) module_name ->
78+
(* This is module-qualified access, add module to dependencies *)
79+
let module_path = { id = member; n = Some module_name; loc } in
80+
path set module_path
81+
| _ ->
82+
(* Regular member access, just process the expression *)
83+
exp set e)
7584
| SEGroup e -> exp set e
76-
| SEEnum p -> path set p
7785
| SERecord { path = p; elems } -> list (fun set (p, v) -> exp (path set p) v) (path set p) elems
7886

7987

@@ -85,9 +93,9 @@ module Dependencies = struct
8593
| SPReal _ -> set
8694
| SPFixed _ -> set
8795
| SPString _ -> set
96+
| SPId _ -> set
8897
| SPTuple elems -> list pattern set elems
8998
| SPGroup e -> pattern set e
90-
| SPEnum p -> path set p
9199

92100

93101
let rec dexp set d =

src/generators/java.ml

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -547,38 +547,55 @@ let print_top_stmt (args : Util.Args.args) t =
547547
{%pla|public static final <#t#> <#name#s> = <#rhs#>;<#>|}
548548

549549

550-
(* Collect type aliases needed based on function signatures *)
550+
(* Extract the base type from a function call in the return statement *)
551+
let extract_base_type_from_call = function
552+
| { e = ECall { path; _ }; _ } when CCString.suffix ~suf:"_type_alloc" path ->
553+
let len = String.length path in
554+
Some (String.sub path 0 (len - 6))
555+
(* Remove "_alloc" *)
556+
| _ -> None
557+
558+
559+
(* Collect type aliases needed based on function signatures and bodies *)
551560
let collect_type_aliases stmts =
552561
let aliases = ref [] in
553562
let collect_from_stmt stmt =
554563
match stmt.top with
555-
| TopFunction (def, _) ->
564+
| TopFunction (def, body) ->
556565
let name = def.name in
557566
(* Look for pattern: *_function_type_alloc that takes arguments (indicating it's a type alias) *)
558567
if String.contains name '_' && CCString.suffix ~suf:"_type_alloc" name && List.length def.args > 0 then
559-
let parts = String.split_on_char '_' name in
560-
(* Handle patterns like Module_noteOn_type_alloc or Module_submodule_pulse_start_type_alloc *)
561-
let len = List.length parts in
562-
if len >= 4 then
563-
(* Check for various patterns including perf variants *)
564-
if len >= 5 && List.nth parts (len - 4) = "perf" then
565-
(* Handle perf patterns like Module_perf_noteOn_type_alloc *)
566-
let module_parts = CCList.take (len - 4) parts in
567-
let module_name = String.concat "_" module_parts in
568-
let name_len = String.length name in
569-
let alias_type = String.sub name 0 (name_len - 6) in
570-
(* Remove "_alloc" *)
571-
let base_type = module_name ^ "_perf_process_type" in
572-
aliases := (alias_type, base_type) :: !aliases
573-
else
574-
(* Handle regular patterns like Module_noteOn_type_alloc or Module_pulse_start_type_alloc *)
575-
let module_parts = CCList.take (len - 3) parts in
576-
let module_name = String.concat "_" module_parts in
577-
let name_len = String.length name in
578-
let alias_type = String.sub name 0 (name_len - 6) in
579-
(* Remove "_alloc" *)
580-
let base_type = module_name ^ "_process_type" in
581-
aliases := (alias_type, base_type) :: !aliases
568+
let name_len = String.length name in
569+
let alias_type = String.sub name 0 (name_len - 6) in
570+
(* Remove "_alloc" *)
571+
(* Try to extract the base type from the function body *)
572+
let base_type =
573+
match body.s with
574+
| StmtReturn exp -> (
575+
match extract_base_type_from_call exp with
576+
| Some base -> base
577+
| None ->
578+
(* Fallback to old logic if we can't parse the body *)
579+
let parts = String.split_on_char '_' name in
580+
let len = List.length parts in
581+
if len >= 4 then
582+
let module_parts = CCList.take (len - 3) parts in
583+
let module_name = String.concat "_" module_parts in
584+
module_name ^ "_process_type"
585+
else
586+
alias_type ^ "_base_type")
587+
| _ ->
588+
(* Fallback if no return statement found *)
589+
let parts = String.split_on_char '_' name in
590+
let len = List.length parts in
591+
if len >= 4 then
592+
let module_parts = CCList.take (len - 3) parts in
593+
let module_name = String.concat "_" module_parts in
594+
module_name ^ "_process_type"
595+
else
596+
alias_type ^ "_base_type"
597+
in
598+
aliases := (alias_type, base_type) :: !aliases
582599
| _ -> ()
583600
in
584601
List.iter collect_from_stmt stmts;

src/generators/js.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ let getTemplateCode (args : Util.Args.args) =
265265
match args.template with
266266
| None -> Pla.unit, Pla.unit
267267
| Some "performance" -> T_performance.generateJs args
268+
| Some "performance-bun" -> T_performance.generateJsBun args
268269
| Some name -> Util.Error.raiseErrorMsg ("Unknown template '" ^ name ^ "'")
269270

270271

src/generators/t_performance.ml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ let luaPost (args : Util.Args.args) =
115115

116116
let generateLua (args : Util.Args.args) = Pla.unit, luaPost args
117117

118-
let jsPost (args : Util.Args.args) =
118+
let jsPostWithLabel (args : Util.Args.args) (label : string) =
119119
let module_name =
120120
match args.files with
121121
| Util.Args.File s :: _ -> Pparser.Parse.moduleName s
@@ -138,12 +138,18 @@ while (samples > 0) {
138138
samples = samples -1;
139139
}
140140
var finish = Number(process.hrtime.bigint() - start) / 1000000 / time;
141-
console.log(`<#module_name#s>\tJs\t${finish.toFixed(2)} ms/s`)
141+
console.log(`<#module_name#s>\t<#label#s>\t${finish.toFixed(2)} ms/s`)
142142
|}
143143

144144

145+
let jsPost (args : Util.Args.args) = jsPostWithLabel args "Js"
146+
147+
let jsBunPost (args : Util.Args.args) = jsPostWithLabel args "Bun"
148+
145149
let generateJs (args : Util.Args.args) = Pla.unit, jsPost args
146150

151+
let generateJsBun (args : Util.Args.args) = Pla.unit, jsBunPost args
152+
147153
let juliaPost (args : Util.Args.args) =
148154
let module_name =
149155
match args.files with

src/mparser/bast.ml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,13 @@ let patt_PattString (loc : Lexing.position * Lexing.position) (s : string) (stat
404404

405405
let patt_PattId (loc : Lexing.position * Lexing.position) (p : 'state -> 'state * path) (state : 'state) :
406406
'state * pattern =
407-
let state, p = p state in
408-
state, { p = SPEnum p; loc = mk_loc state loc }
407+
let state, path = p state in
408+
(* Allow identifier patterns - inference will validate if they're enum constructors *)
409+
match path with
410+
| { id; n = None; _ } -> state, { p = SPId id; loc = mk_loc state loc }
411+
| { id; n = Some module_name; _ } ->
412+
(* Module-qualified enum patterns like Module.EnumValue *)
413+
state, { p = SPId (module_name ^ "_" ^ id); loc = mk_loc state loc }
409414

410415

411416
let patt_PattGroup (loc : Lexing.position * Lexing.position) (p : 'state -> 'state * pattern) (state : 'state) :

0 commit comments

Comments
 (0)