diff --git a/files.test.ts b/files.test.ts index 2db9919..10f6f99 100644 --- a/files.test.ts +++ b/files.test.ts @@ -17,7 +17,6 @@ async function compile_script(filename: string, test_name: string) { const code = await readFile(filename, { encoding: "utf-8" }); const patterns = core_patterns(parse); const globals = get_globals("es2024.full"); - const global_macros = Object.keys(patterns); const [global_unit, global_context] = init_global_context(patterns, globals); const helpers: preexpand_helpers = { manager: { @@ -30,6 +29,9 @@ async function compile_script(filename: string, test_name: string) { get_import_path(_cuid) { throw new Error(`imports are not supported in tests`); }, + resolve_rib(_rib_id, _cuid) { + throw new Error(`imports are not supported in gui`); + }, }, global_unit, global_context, @@ -41,7 +43,7 @@ async function compile_script(filename: string, test_name: string) { package: { name: "@rewrite-ts/test", version: "0.0.0" }, path: filename, }; - const [_loc0, expand] = initial_step(parse(code, source_file), test_name, globals, global_macros); + const [_loc0, expand] = initial_step(parse(code, source_file), test_name, ["es2024.full"]); const result = await (async () => { try { const { loc } = await expand(helpers); diff --git a/rtsc/.rts/testing-file-extensions.rts.json b/rtsc/.rts/testing-file-extensions.rts.json index 155d0d1..bc9aa65 100644 --- a/rtsc/.rts/testing-file-extensions.rts.json +++ b/rtsc/.rts/testing-file-extensions.rts.json @@ -1,10 +1,10 @@ { "cid": "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", - "cookie": "rewrite-ts-010", + "cookie": "rewrite-ts-013", "exported_identifiers": { "x": [ { - "type": "value", + "type": "lexical", "label": { "cuid": "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", "name": "l2" @@ -109,5 +109,78 @@ }, "l4": {"type": "type", "name": "t_local_3"}, "l5": {"type": "type", "name": "t_global_4"} + }, + "unit": { + "cu_id": "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + "store": { + "r0": { + "type": "rib", + "normal_env": { + "y": [ + [ + [ + "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + "name": "l1" + } + ] + ], + "x": [ + [ + [ + "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + "name": "l2" + } + ] + ], + "foo": [ + [ + [ + "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + "name": "l3" + } + ] + ] + }, + "types_env": { + "t_local": [ + [ + [ + "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + "name": "l4" + } + ] + ], + "t_global": [ + [ + [ + "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "rtsc/testing-file-extensions.rts rewrite-ts-visualized 0.0.0", + "name": "l5" + } + ] + ] + }, + "libs": ["es2024.full"] + } + } } } \ No newline at end of file diff --git a/rtsc/watch.ts b/rtsc/watch.ts index 0cb17c0..cd2c316 100755 --- a/rtsc/watch.ts +++ b/rtsc/watch.ts @@ -4,13 +4,13 @@ import { basename, dirname, join } from "node:path"; import TS from "typescript"; import {} from "./testing-file-extensions.rts.ts"; import { LibraryManager } from "../src/library-manager.ts"; -import { get_globals, init_global_context } from "../src/global-module.ts"; +import { get_globals } from "../src/global-module.ts"; import { core_patterns } from "../src/syntax-core-patterns.ts"; import { parse } from "../src/parse.ts"; const globals = get_globals("es2024.full"); const patterns = core_patterns(parse); -const library_manager = new LibraryManager(patterns, globals); +const library_manager = new LibraryManager(patterns, globals, ["es2024.full"]); const watch_reporter: TS.WatchStatusReporter = (diagnostics, _newline, _options, error_count) => { console.log(`rtsc: ${diagnostics.messageText}`); @@ -29,7 +29,7 @@ const diagnostics_reporter: TS.DiagnosticReporter = (diagnostics) => { category, messageText, start, - relatedInformation, + relatedInformation: _relatedInformation, reportsDeprecated, reportsUnnecessary, source, diff --git a/src/expander.ts b/src/expander.ts index 54ac44a..b698e14 100644 --- a/src/expander.ts +++ b/src/expander.ts @@ -32,8 +32,7 @@ import { counters, data, swalker, walker, walkerplus } from "./data"; export function initial_step( ast: AST, cu_id: string, - globals: string[], - global_macros: string[], + libs: string[], ): [ Loc, (helpers: preexpand_helpers) => Promise<{ @@ -43,7 +42,7 @@ export function initial_step( modular: modular_extension; }>, ] { - const { stx, counters, unit, rib, rib_id } = init_top_level(ast, cu_id, globals, global_macros); + const { stx, counters, unit, rib, rib_id } = init_top_level(ast, cu_id, libs); const initial_loc: Loc = mkzipper(stx); const lexical: lexical_extension = { extensible: true, rib, rib_id }; const empty_rib: Rib = { type: "rib", normal_env: {}, types_env: {} }; @@ -225,7 +224,7 @@ const list_handlers_table: { [tag in list_tag]: "descend" | "stop" | "todo" } = variable_declarator: "stop", export_specifier: "todo", export_clause: "todo", - export_declaration: "todo", + export_declaration: "stop", named_exports: "todo", slice: "descend", arrow_function: "stop", @@ -355,6 +354,7 @@ const preexpand_forms = ), ); } + case "imported_syntax_rules_transformer": case "syntax_rules_transformer": { const { clauses } = binding; return data.helpers.inspect(loc, `transformer form`, () => @@ -395,6 +395,7 @@ const preexpand_forms = ); } switch (loc.t.tag) { + case "export_declaration": case "arrow_function": return next(loc); case "member_expression": @@ -700,6 +701,14 @@ function string_literal(value: string): STX { }; } +const empty_slice: STX = { + type: "list", + tag: "slice", + content: null, + wrap: empty_wrap, + src: false, +}; + const export_keyword: STX = { type: "atom", tag: "other", @@ -1022,6 +1031,56 @@ const postexpand_lexical_declaration: walker = async ({ loc, ...data }) => { }).then(insert_export_keyword); }; +const postexpand_export_declaration: walker = ({ loc: main_loc, ...data }) => { + const handle_identifier: walker = async ({ loc, modular, context, unit, helpers, ...data }) => { + assert(modular.extensible); + assert(loc.t.tag === "identifier"); + const { content, wrap } = loc.t; + const resolution = await resolve(content, wrap, context, unit, "normal_env", helpers); + if (resolution.type !== "bound") syntax_error(loc, "unbound identifier"); + const new_modular = extend_modular( + modular, + true, + content, + wrap.marks, + resolution.label, + "normal_env", + loc, + ); + return go_right(loc, (loc) => + after_identifier({ loc, modular: new_modular, context, unit, helpers, ...data }), + ); + }; + const after_identifier: walker = ({ loc, ...data }) => + loc.t.content === "}" ? Promise.resolve({ loc, ...data }) : debug(loc, "TODO"); + + const expect_export: walker = ({ loc, ...data }) => + loc.t.content === "}" + ? Promise.resolve({ loc, ...data }) + : loc.t.tag === "identifier" + ? handle_identifier({ loc, ...data }) + : syntax_error(loc); + + const start: walker = ({ loc, ...data }) => + loc.t.content === "export" + ? go_right(loc, (loc) => + go_down(loc, (loc) => + loc.t.content === "{" + ? go_right(loc, (loc) => expect_export({ loc, ...data })) + : syntax_error(loc), + ), + ) + : syntax_error(loc); + + if (!data.modular.extensible) syntax_error(main_loc, "invalid context for export"); + return go_down(main_loc, (loc) => + start({ loc, ...data }).then((data) => ({ + ...data, + loc: change(main_loc, mkzipper(empty_slice)), + })), + ); +}; + function rename(loc: Loc, new_name: string): Loc { const new_id: STX = { type: "atom", @@ -1137,6 +1196,9 @@ const postexpand_body = (sort: "type" | "value") => (data: data) => { case "type_alias_declaration": { return postexpand_type_alias_declaration({ ...data, loc }).then(cont); } + case "export_declaration": { + return postexpand_export_declaration({ ...data, loc }).then(cont); + } case "member_expression": { return go_down(loc, (loc) => in_isolation(loc, (loc) => postexpand_forms(sort)({ ...data, loc })) diff --git a/src/library-manager.ts b/src/library-manager.ts index 7d38434..326bc36 100644 --- a/src/library-manager.ts +++ b/src/library-manager.ts @@ -15,11 +15,11 @@ import { } from "./preexpand-helpers"; import { AST, source_file } from "./ast"; import { normalize } from "node:path"; -import { Binding, CompilationUnit, Context, Loc } from "./syntax-structures"; +import { Binding, CompilationUnit, Context, Loc, Rib } from "./syntax-structures"; import stringify from "json-stringify-pretty-compact"; import { init_global_context } from "./global-module"; -const cookie = "rewrite-ts-010"; +const cookie = "rewrite-ts-013"; type module_state = | { type: "initial" } @@ -31,6 +31,7 @@ type module_state = pkg_relative_path: string; exported_identifiers: { [name: string]: import_resolution[] }; context: Context; + unit: CompilationUnit; } | { type: "error"; reason: string }; @@ -38,8 +39,7 @@ class RtsModule implements imported_module { private path: string; private library_manager: LibraryManager; private state: module_state = { type: "initial" }; - private globals: string[]; - private global_macros: string[]; + private libs: string[]; private global_unit: CompilationUnit; private global_context: Context; public imported_modules: imported_module[] = []; @@ -47,15 +47,13 @@ class RtsModule implements imported_module { constructor( path: string, library_manager: LibraryManager, - globals: string[], - global_macros: string[], + libs: string[], global_unit: CompilationUnit, global_context: Context, ) { this.path = path; this.library_manager = library_manager; - this.globals = globals; - this.global_macros = global_macros; + this.libs = libs; this.global_unit = global_unit; this.global_context = global_context; } @@ -121,6 +119,7 @@ class RtsModule implements imported_module { pkg_relative_path, exported_identifiers: json.exported_identifiers, context: json.context, + unit: json.unit, }; } @@ -134,12 +133,7 @@ class RtsModule implements imported_module { package: { name: my_pkg.name, version: my_pkg.version }, path: my_path, }; - const [_loc0, expand] = initial_step( - parse(code, source_file), - this.state.cid, - this.globals, - this.global_macros, - ); + const [_loc0, expand] = initial_step(parse(code, source_file), this.state.cid, this.libs); try { const helpers: preexpand_helpers = { manager: { @@ -150,12 +144,12 @@ class RtsModule implements imported_module { return mod; }, resolve_label: async (label) => { - const mod = await this.find_module_by_cid(label.cuid); + const mod = this.find_module_by_cid(label.cuid); if (!mod) throw new Error(`cannot find module with cuid = ${label.cuid}`); return mod.resolve_label(label.name); }, get_import_path: async (cuid) => { - const mod = await this.find_module_by_cid(cuid); + const mod = this.find_module_by_cid(cuid); if (!mod) throw new Error(`cannot find module with cuid = ${cuid}`); const [mod_pkg, mod_path] = mod.get_pkg_and_path(); if (mod_pkg === my_pkg) { @@ -167,6 +161,11 @@ class RtsModule implements imported_module { throw new Error(`TODO cross package imports`); } }, + resolve_rib: (rib_id, cuid) => { + const mod = this.find_module_by_cid(cuid); + if (!mod) throw new Error(`cannot find module with cuid = ${cuid}`); + return mod.resolve_rib(rib_id); + }, }, global_unit: this.global_unit, global_context: this.global_context, @@ -174,19 +173,24 @@ class RtsModule implements imported_module { return k(); }, }; - const { loc, unit: _unit, context, modular } = await expand(helpers); + const { loc, unit, context, modular } = await expand(helpers); assert(modular.extensible); const proxy_code = generate_proxy_code( this.get_generated_code_relative_path(), modular, context, ); - const exported_identifiers = get_exported_identifiers_from_rib(modular.explicit); + const exported_identifiers = get_exported_identifiers_from_rib( + modular.explicit, + this.state.cid, + context, + ); const json_content = { cid: this.state.cid, cookie, exported_identifiers, context, + unit, }; const code_path = this.get_generated_code_absolute_path(); await fs.mkdir(dirname(code_path), { recursive: true }); @@ -216,7 +220,7 @@ class RtsModule implements imported_module { return resolutions; } - async get_cid(): Promise { + get_cid(): string { //await this.ensureUpToDate(); switch (this.state.type) { case "fresh": @@ -227,10 +231,10 @@ class RtsModule implements imported_module { } } - async find_module_by_cid(cid: string): Promise { - if ((await this.get_cid()) === cid) return this; + find_module_by_cid(cid: string): imported_module | undefined { + if (this.get_cid() === cid) return this; for (const m of this.imported_modules) { - const r = await m.find_module_by_cid(cid); + const r = m.find_module_by_cid(cid); if (r) return r; } return undefined; @@ -245,6 +249,12 @@ class RtsModule implements imported_module { return { type: "imported_lexical", cuid: this.state.cid, name: binding.name }; case "type": return { type: "imported_type", cuid: this.state.cid, name: binding.name }; + case "syntax_rules_transformer": + return { + type: "imported_syntax_rules_transformer", + cuid: this.state.cid, + clauses: binding.clauses, + }; default: throw new Error(`unhandled binding type ${binding.type}`); } @@ -269,6 +279,14 @@ class RtsModule implements imported_module { this.imported_modules.push(mod); return mod; } + + resolve_rib(rib_id: string): Rib { + assert(this.state.type === "fresh"); + const unit = this.state.unit; + const rib = unit.store[rib_id]; + assert(rib !== undefined); + return rib; + } } class Package { @@ -284,16 +302,14 @@ class Package { } export class LibraryManager { - private globals: string[]; - private global_macros: string[]; + private libs: string[]; private global_unit: CompilationUnit; private global_context: Context; private modules: { [path: string]: imported_module } = {}; private packages: { [dir: string]: Package } = {}; - constructor(patterns: { [k: string]: AST }, globals: string[]) { - this.globals = globals; - this.global_macros = Object.keys(patterns); + constructor(patterns: { [k: string]: AST }, globals: string[], libs: string[]) { + this.libs = libs; const [global_unit, global_context] = init_global_context(patterns, globals); this.global_unit = global_unit; this.global_context = global_context; @@ -303,8 +319,7 @@ export class LibraryManager { const mod = (this.modules[path] ??= new RtsModule( path, this, - this.globals, - this.global_macros, + this.libs, this.global_unit, this.global_context, )); diff --git a/src/preexpand-handlers.ts b/src/preexpand-handlers.ts index b061ea3..2e86ebd 100644 --- a/src/preexpand-handlers.ts +++ b/src/preexpand-handlers.ts @@ -9,7 +9,7 @@ import { rib_push, } from "./stx"; import { syntax_error } from "./stx-error"; -import { CompilationUnit, Context, Loc, STX } from "./syntax-structures"; +import { Binding, CompilationUnit, Context, Loc, STX } from "./syntax-structures"; import { list_tag } from "./tags"; import { change, go_down, go_right, go_up, mkzipper } from "./zipper"; @@ -182,16 +182,19 @@ const import_declaration: walker = async ({ loc, helpers, ...data }) => { ); assert(lexical.extensible); const { rib, rib_id } = lexical; + const where: { [k in Binding["type"]]: "types_env" | "normal_env" | "both" } = { + type: "types_env", + lexical: "normal_env", + imported_lexical: "normal_env", + imported_type: "types_env", + core_syntax: "both", + ts: "both", + syntax_rules_transformer: "both", + imported_syntax_rules_transformer: "both", + }; const new_rib = resolutions.reduce((rib, resolution) => { assert(typeof resolution.label !== "string"); - return rib_push( - rib, - name, - wrap.marks, - resolution.label, - { type: "types_env" as const, value: "normal_env" as const }[resolution.type], - loc0, - ); + return rib_push(rib, name, wrap.marks, resolution.label, where[resolution.type], loc0); }, rib); const new_lexical: lexical_extension = { extensible: true, rib: new_rib, rib_id }; const new_unit = extend_unit(unit, new_lexical); diff --git a/src/preexpand-helpers.ts b/src/preexpand-helpers.ts index 97a6110..a65c964 100644 --- a/src/preexpand-helpers.ts +++ b/src/preexpand-helpers.ts @@ -4,7 +4,7 @@ import { Binding, CompilationUnit, Context, Label, Loc, Rib } from "./syntax-str type inspect = (loc: Loc, reason: string, k: () => Promise) => Promise; export type import_resolution = { - type: "type" | "value"; + type: Binding["type"]; label: Label; }; @@ -12,16 +12,18 @@ export type imported_module = { imported_modules: imported_module[]; resolve_exported_identifier: (name: string, loc: Loc) => Promise; ensureUpToDate(): Promise; - get_cid(): Promise; - find_module_by_cid(cid: string): Promise; + get_cid(): string; + find_module_by_cid(cid: string): imported_module | undefined; resolve_label(name: string): Promise; get_pkg_and_path(): [{ name: string; version: string }, string]; + resolve_rib: (rib_id: string) => Rib; }; export type manager = { resolve_import: (loc: Loc) => Promise; resolve_label: (label: Label) => Promise; get_import_path: (cuid: string) => Promise; + resolve_rib: (rib_id: string, cuid: string) => Rib; }; export type preexpand_helpers = { @@ -35,19 +37,27 @@ type exported_identifiers = { [name: string]: import_resolution[]; }; -export function get_exported_identifiers_from_rib(rib: Rib): exported_identifiers { +export function get_exported_identifiers_from_rib( + rib: Rib, + cuid: string, + context: Context, +): exported_identifiers { const ids: exported_identifiers = {}; Object.entries(rib.normal_env).forEach(([lhs, rhs]) => { const b = (ids[lhs] ??= []); assert(rhs.length === 1); const [_marks, label] = rhs[0]; - b.push({ type: "value", label }); + assert(label.cuid === cuid, `export of import?`); + const binding = context[label.name]; + b.push({ type: binding.type, label }); }); Object.entries(rib.types_env).forEach(([lhs, rhs]) => { const b = (ids[lhs] ??= []); assert(rhs.length === 1); const [_marks, label] = rhs[0]; - b.push({ type: "type", label }); + assert(label.cuid === cuid, `export of import?`); + const binding = context[label.name]; + b.push({ type: binding.type, label }); }); return ids; } diff --git a/src/proxy-code.ts b/src/proxy-code.ts index 49dbf8b..79a301c 100644 --- a/src/proxy-code.ts +++ b/src/proxy-code.ts @@ -18,9 +18,12 @@ function extract_bindings( const [_marks, label] = ls[0]; const binding = context[label.name]; assert(binding !== undefined); - assert(binding.type === binding_type); - const new_name = binding.name; - a[original_name] = new_name; + if (binding.type === binding_type) { + const new_name = binding.name; + a[original_name] = new_name; + } else { + assert(binding.type === "syntax_rules_transformer"); + } }); return a; } diff --git a/src/stx.ts b/src/stx.ts index 94782eb..34d4af9 100644 --- a/src/stx.ts +++ b/src/stx.ts @@ -17,12 +17,15 @@ import { STX, Subst, top_mark, + top_marks, Wrap, } from "./syntax-structures"; -import { globals_cuid, init_global_unit } from "./global-module"; +import { get_globals, globals_cuid } from "./global-module"; import { syntax_error } from "./stx-error"; import { preexpand_helpers } from "./preexpand-helpers"; import { counters } from "./data"; +import { core_handlers } from "./syntax-core-patterns"; +import { stdlibs } from "./generated-stdlibs"; function is_top_marked(wrap: Wrap): boolean { function loop_marks(marks: Marks): boolean { @@ -37,6 +40,20 @@ function same_marks(m1: Marks, m2: Marks): boolean { return m1 === null ? m2 === null : m2 !== null && m1[0] === m2[0] && same_marks(m1[1], m2[1]); } +function global_resolve(libname: string, idname: string): boolean { + const lib = stdlibs[libname]; + if (!lib) throw new Error(`invalid lib name '${libname}'`); + return ( + lib.value?.includes(idname) || + lib.type?.includes(idname) || + lib.module?.includes(idname) || + lib.interface?.includes(idname) || + lib.class?.includes(idname) || + lib.include?.some((x) => global_resolve(x, idname)) || + false + ); +} + function id_to_label( name: string, marks: Marks, @@ -63,17 +80,25 @@ function id_to_label( return rib; } else { // need to resolve name, marks in imported rib? - throw new Error(`unhandled imported rib? ${name} ${cu_id}, ${JSON.stringify(marks)}`); + const rib = helpers.manager.resolve_rib(rib_id, cu_id); + return rib; } })(subst[0]); const ls = rib[resolution_type][name]; const entry = ls?.find(([ms, _]) => same_marks(ms, marks)); + if (entry) return entry[1]; + if (rib.libs) { + if (core_handlers[name]) { + return { cuid: globals_cuid, name: `global.${name}` }; + } + for (const lib of rib.libs) { + if (global_resolve(lib, name)) { + return { cuid: globals_cuid, name: `global.${name}` }; + } + } + } if (entry === undefined) return lookup(marks, subst[1]); const label = entry[1]; - if (typeof label === "string") { - console.error(rib); - throw new Error(`invalid label`); - } return label; } return lookup(marks, subst); @@ -144,9 +169,19 @@ export function rib_push( name: string, marks: Marks, label: Label, - env_type: "normal_env" | "types_env", + env_type: "normal_env" | "types_env" | "both", loc: Loc, ): Rib { + if (env_type === "both") { + return rib_push( + rib_push(rib, name, marks, label, "normal_env", loc), + name, + marks, + label, + "types_env", + loc, + ); + } const env = rib[env_type]; const entry = env[name] ?? []; if (entry.find((x) => same_marks(x[0], marks))) { @@ -287,8 +322,7 @@ export type CorePatterns = { [k: string]: AST }; export function init_top_level( ast: AST, cuid: string, - globals: string[], - global_macros: string[], + libs: string[], ): { stx: STX; counters: counters; @@ -298,10 +332,19 @@ export function init_top_level( } { const initial_counters: counters = { internal: 0, vars: 1 }; const [rib_id, counters] = new_rib_id(initial_counters); - const { top_wrap, rib, unit } = init_global_unit(cuid, rib_id, globals, global_macros); + + const marks: Marks = [cuid, top_marks]; + const top_wrap: Wrap = { marks, subst: [{ rib_id, cu_id: cuid }, null], aes: null }; + const rib: Rib = { type: "rib", normal_env: {}, types_env: {}, libs: libs }; function wrap(ast: AST): STX { return { ...ast, wrap: top_wrap, src: ast }; } + const unit: CompilationUnit = { + cu_id: cuid, + store: { + [rib_id]: rib, + }, + }; return { stx: wrap(ast), counters, diff --git a/src/syntax-core-patterns.ts b/src/syntax-core-patterns.ts index dc8106f..107a2be 100644 --- a/src/syntax-core-patterns.ts +++ b/src/syntax-core-patterns.ts @@ -276,12 +276,12 @@ const splice: walker = async ({ loc, context, unit, lexical, helpers, ...data }) }; }; -function literal_binding( +async function literal_binding( name: string, subst: subst, unit: CompilationUnit, helpers: preexpand_helpers, -): boolean { +): Promise { const x = subst.find(([lhs]) => lhs.content === name); assert(x !== undefined); const lhs = x[0]; diff --git a/src/syntax-structures.ts b/src/syntax-structures.ts index 4bfe94e..edbf789 100644 --- a/src/syntax-structures.ts +++ b/src/syntax-structures.ts @@ -41,7 +41,7 @@ export type Label = { cuid: string; name: string }; export type Env = { [name: string]: [LL, Label][] }; -export type Rib = { type: "rib"; types_env: Env; normal_env: Env }; +export type Rib = { type: "rib"; types_env: Env; normal_env: Env; libs?: string[] }; function label_generator(prefix: string): (counters: counters) => [string, counters] { return (counters: counters) => [ @@ -85,6 +85,11 @@ export type Binding = | { type: "syntax_rules_transformer"; clauses: { pattern: Loc; template: STX }[] } | { type: "imported_lexical"; name: string; cuid: string } | { type: "imported_type"; name: string; cuid: string } + | { + type: "imported_syntax_rules_transformer"; + clauses: { pattern: Loc; template: STX }[]; + cuid: string; + } | { type: "ts"; name: string }; export type Context = { [label: string]: Binding }; diff --git a/test-project/.rts/main.rts.json b/test-project/.rts/main.rts.json index 1e76d28..4a1f1db 100644 --- a/test-project/.rts/main.rts.json +++ b/test-project/.rts/main.rts.json @@ -1,6 +1,79 @@ { "cid": "test-project/main.rts rewrite-ts-visualized 0.0.0", - "cookie": "rewrite-ts-010", + "cookie": "rewrite-ts-013", "exported_identifiers": {}, - "context": {"l1": {"type": "lexical", "name": "y_1"}} + "context": {"l1": {"type": "lexical", "name": "y_1"}}, + "unit": { + "cu_id": "test-project/main.rts rewrite-ts-visualized 0.0.0", + "store": { + "r0": { + "type": "rib", + "normal_env": { + "fref": [ + [ + [ + "test-project/main.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l4" + } + ] + ], + "x": [ + [ + [ + "test-project/main.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l1" + } + ] + ], + "y": [ + [ + [ + "test-project/main.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/main.rts rewrite-ts-visualized 0.0.0", + "name": "l1" + } + ] + ] + }, + "types_env": { + "fref": [ + [ + [ + "test-project/main.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l4" + } + ] + ], + "t": [ + [ + [ + "test-project/main.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l2" + } + ] + ] + }, + "libs": ["es2024.full"] + } + } + } } \ No newline at end of file diff --git a/test-project/.rts/main.rts.ts b/test-project/.rts/main.rts.ts index e710bb7..b341a40 100644 --- a/test-project/.rts/main.rts.ts +++ b/test-project/.rts/main.rts.ts @@ -1,3 +1,3 @@ -import { type t_2 as t_2, x_1 as x_3 } from "./mod.rts.ts"; -export const y_1: t_2 = x_3; +import { type t_2 as t_2, x_1 as x_3, f_3 as f_4 } from "./mod.rts.ts"; +export const y_1: t_2 = x_3 + f_4; console.log(y_1); diff --git a/test-project/.rts/mod.rts.json b/test-project/.rts/mod.rts.json index be7dd12..491c564 100644 --- a/test-project/.rts/mod.rts.json +++ b/test-project/.rts/mod.rts.json @@ -1,16 +1,25 @@ { "cid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", - "cookie": "rewrite-ts-010", + "cookie": "rewrite-ts-013", "exported_identifiers": { "x": [ { - "type": "value", + "type": "lexical", "label": { "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", "name": "l1" } } ], + "fref": [ + { + "type": "syntax_rules_transformer", + "label": { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l4" + } + } + ], "t": [ { "type": "type", @@ -23,6 +32,151 @@ }, "context": { "l1": {"type": "lexical", "name": "x_1"}, - "l2": {"type": "type", "name": "t_2"} + "l2": {"type": "type", "name": "t_2"}, + "l3": {"type": "lexical", "name": "f_3"}, + "l4": { + "type": "syntax_rules_transformer", + "clauses": [ + { + "pattern": { + "type": "loc", + "t": { + "type": "atom", + "wrap": { + "marks": [ + "test-project/mod.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + "subst": [ + { + "rib_id": "r0", + "cu_id": "test-project/mod.rts rewrite-ts-visualized 0.0.0" + }, + null + ], + "aes": null + }, + "tag": "identifier", + "content": "fref", + "src": { + "type": "atom", + "tag": "identifier", + "content": "fref", + "src": { + "type": "origin", + "p": 88, + "e": 93, + "f": { + "package": { + "name": "rewrite-ts-visualized", + "version": "0.0.0" + }, + "path": "test-project/mod.rts" + } + } + } + }, + "p": {"type": "top"} + }, + "template": { + "type": "atom", + "wrap": { + "marks": [ + "test-project/mod.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + "subst": [ + { + "rib_id": "r0", + "cu_id": "test-project/mod.rts rewrite-ts-visualized 0.0.0" + }, + null + ], + "aes": null + }, + "tag": "identifier", + "content": "f", + "src": { + "type": "atom", + "tag": "identifier", + "content": "f", + "src": { + "type": "origin", + "p": 94, + "e": 96, + "f": { + "package": { + "name": "rewrite-ts-visualized", + "version": "0.0.0" + }, + "path": "test-project/mod.rts" + } + } + } + } + } + ] + } + }, + "unit": { + "cu_id": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "store": { + "r0": { + "type": "rib", + "normal_env": { + "x": [ + [ + [ + "test-project/mod.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l1" + } + ] + ], + "f": [ + [ + [ + "test-project/mod.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l3" + } + ] + ], + "fref": [ + [ + [ + "test-project/mod.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l4" + } + ] + ] + }, + "types_env": { + "t": [ + [ + [ + "test-project/mod.rts rewrite-ts-visualized 0.0.0", + ["top", null] + ], + { + "cuid": "test-project/mod.rts rewrite-ts-visualized 0.0.0", + "name": "l2" + } + ] + ] + }, + "libs": ["es2024.full"] + } + } } } \ No newline at end of file diff --git a/test-project/.rts/mod.rts.ts b/test-project/.rts/mod.rts.ts index 8c434d9..e9ab0f9 100644 --- a/test-project/.rts/mod.rts.ts +++ b/test-project/.rts/mod.rts.ts @@ -1,2 +1,3 @@ export const x_1 = 12; export type t_2 = number; +export const f_3 = 13; diff --git a/test-project/main.rts b/test-project/main.rts index 4a68c9c..2753fe8 100644 --- a/test-project/main.rts +++ b/test-project/main.rts @@ -1,3 +1,3 @@ -import { x, t } from "./mod.rts"; -const y: t = x; +import { x, t, fref } from "./mod.rts"; +const y: t = x + fref; console.log(y); diff --git a/test-project/mod.rts b/test-project/mod.rts index 8be0c45..c4fd489 100644 --- a/test-project/mod.rts +++ b/test-project/mod.rts @@ -1,2 +1,8 @@ export const x = 12; export type t = number; + +const f = 13; + +define_rewrite_rules([fref, fref, f]); + +export {fref}; diff --git a/ui/App.tsx b/ui/App.tsx index c20c536..4286368 100644 --- a/ui/App.tsx +++ b/ui/App.tsx @@ -91,22 +91,16 @@ function StepperView({ step, step_number }: { step: Step; step_number: number }) function Example({ code, onChange }: ExampleProps) { type expand = (helpers: preexpand_helpers) => Promise<{ loc: Loc }>; - const globals = get_globals("es2024.full"); - const patterns = core_patterns(parse); - const global_macros = Object.keys(patterns); function init_state(code: string): [State, expand] { const source_file: source_file = { package: { name: "@rewrite-ts/example", version: "0.0.0" }, path: "example", }; - const [loc0, expand] = initial_step( - parse(code, source_file), - "example", - globals, - global_macros, - ); + const [loc0, expand] = initial_step(parse(code, source_file), "example", ["es2024.full"]); return [initial_state(loc0), expand]; } + const globals = get_globals("es2024.full"); + const patterns = core_patterns(parse); const [global_unit, global_context] = init_global_context(patterns, globals); const [state, setState] = useState(init_state(code)[0]); useEffect(() => { @@ -136,6 +130,9 @@ function Example({ code, onChange }: ExampleProps) { get_import_path(_cuid) { throw new Error(`imports are not supported in gui`); }, + resolve_rib(_rib_id, _cuid) { + throw new Error(`imports are not supported in gui`); + }, }, global_unit, global_context,