answer the module question: the partition is a path, and there is no namespacing
This commit is contained in:
@@ -2797,6 +2797,12 @@ fn params_to_env_args(params: [Any]) -> String {
|
||||
fn cg_fn(stmt: Map<String, Any>) -> Void {
|
||||
let fn_name: String = stmt["name"]
|
||||
state_set("__cg_current_fn", fn_name)
|
||||
// Record every top-level definition. El has NO namespacing -- imports are
|
||||
// textual inlining, so two modules defining the same name emit two C
|
||||
// functions into one translation unit. cc catches it, but names the
|
||||
// generated helpers first and the user's fn fourth. Recording it lets the
|
||||
// collision be reported at El level, in El terms.
|
||||
record_call(fn_name, "defines")
|
||||
// Emit which constructs this fn carries, so the prohibition check can be a
|
||||
// query over relations instead of a walk inside the emitter.
|
||||
let cdl = stmt["decorators"]
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Control for duplicate-definition detection.
|
||||
#
|
||||
# El has no namespacing: import is textual inlining, so two modules defining the
|
||||
# same name emit two C functions into one translation unit.
|
||||
set -uo pipefail
|
||||
ELC="${1:?usage: definitions_query.sh <elc>}"
|
||||
LANG_DIR="${2:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
||||
W=$(mktemp -d); trap 'rm -rf "$W"' EXIT; F=0
|
||||
chk(){ [ "$2" = "$3" ] && printf ' ok %s\n' "$1" || { printf ' FAIL %s\n expected %s got %s\n' "$1" "$2" "$3"; F=$((F+1)); }; }
|
||||
|
||||
printf 'fn helper() -> Int { return 1 }\n' > "$W/a.el"
|
||||
printf 'fn helper() -> Int { return 2 }\n' > "$W/b.el"
|
||||
printf 'import "a.el"\nimport "b.el"\nfn main() { println(int_to_str(helper())) }\n' > "$W/m.el"
|
||||
EL_RELATIONS_OUT="$W/r.txt" "$ELC" "$W/m.el" >/dev/null 2>&1
|
||||
out=$("$LANG_DIR/tools/check/definitions.sh" "$W/r.txt" 2>&1); rc=$?
|
||||
chk "a collision across modules is caught at El level" "1" "$rc"
|
||||
chk "the colliding name is reported" "1" "$(echo "$out" | grep -c "'helper' is defined 2 times")"
|
||||
chk "and the reason is given" "1" "$(echo "$out" | grep -c 'no namespacing')"
|
||||
|
||||
printf 'fn only_once() -> Int { return 1 }\nfn main() { println(int_to_str(only_once())) }\n' > "$W/c.el"
|
||||
EL_RELATIONS_OUT="$W/r2.txt" "$ELC" "$W/c.el" >/dev/null 2>&1
|
||||
"$LANG_DIR/tools/check/definitions.sh" "$W/r2.txt" >/dev/null 2>&1
|
||||
chk "a clean program exits 0" "0" "$?"
|
||||
echo; echo " 4 assertions, $((4-F)) passed, $F failed"; exit $F
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# definitions.sh — catch duplicate top-level definitions at El level.
|
||||
#
|
||||
# El has no namespacing. `import` is textual inlining, so two modules defining
|
||||
# the same name emit two C functions into one translation unit. cc does catch
|
||||
# it, but reports the generated helpers (__el_body_f, __env_f, __thunk_f) before
|
||||
# the user's own function, so the first three errors name symbols the user never
|
||||
# wrote.
|
||||
#
|
||||
# LIMIT, stated rather than hidden: textual inlining destroys file provenance.
|
||||
# By the time codegen runs there is one source string and no record of which
|
||||
# file a definition came from, so this can say WHICH name collides but not which
|
||||
# files. Naming the files needs provenance threaded through resolve_imports.
|
||||
set -uo pipefail
|
||||
REL="${1:?usage: definitions.sh <relations-file>}"
|
||||
[ -f "$REL" ] || exit 0
|
||||
V=0
|
||||
while read -r name count; do
|
||||
[ "$count" -gt 1 ] || continue
|
||||
printf "duplicate definition: '%s' is defined %s times — El has no namespacing, so imported modules share one global scope\n" "$name" "$count"
|
||||
V=$((V+1))
|
||||
done < <(grep ' calls defines$' "$REL" | awk '{print $1}' | sort | uniq -c | awk '{print $2, $1}')
|
||||
[ "$V" -eq 0 ] && echo "definitions: clean"
|
||||
exit "$V"
|
||||
Reference in New Issue
Block a user