semantifold 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/README.md +71 -0
- package/build/index.d.ts +54 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +45 -0
- package/build/src/backends/identifiers.d.ts +19 -0
- package/build/src/backends/identifiers.d.ts.map +1 -0
- package/build/src/backends/identifiers.js +93 -0
- package/build/src/backends/index.d.ts +35 -0
- package/build/src/backends/index.d.ts.map +1 -0
- package/build/src/backends/index.js +149 -0
- package/build/src/backends/java.d.ts +8 -0
- package/build/src/backends/java.d.ts.map +1 -0
- package/build/src/backends/java.js +172 -0
- package/build/src/backends/javascript.d.ts +8 -0
- package/build/src/backends/javascript.d.ts.map +1 -0
- package/build/src/backends/javascript.js +173 -0
- package/build/src/backends/php.d.ts +8 -0
- package/build/src/backends/php.d.ts.map +1 -0
- package/build/src/backends/php.js +175 -0
- package/build/src/backends/ruby.d.ts +8 -0
- package/build/src/backends/ruby.d.ts.map +1 -0
- package/build/src/backends/ruby.js +155 -0
- package/build/src/backends/scalars.d.ts +15 -0
- package/build/src/backends/scalars.d.ts.map +1 -0
- package/build/src/backends/scalars.js +138 -0
- package/build/src/backends/shared.d.ts +26 -0
- package/build/src/backends/shared.d.ts.map +1 -0
- package/build/src/backends/shared.js +424 -0
- package/build/src/backends/typescript.d.ts +8 -0
- package/build/src/backends/typescript.d.ts.map +1 -0
- package/build/src/backends/typescript.js +160 -0
- package/build/src/backends/writer.d.ts +87 -0
- package/build/src/backends/writer.d.ts.map +1 -0
- package/build/src/backends/writer.js +207 -0
- package/build/src/diagnostic.d.ts +67 -0
- package/build/src/diagnostic.d.ts.map +1 -0
- package/build/src/diagnostic.js +96 -0
- package/build/src/frontends/index.d.ts +14 -0
- package/build/src/frontends/index.d.ts.map +1 -0
- package/build/src/frontends/index.js +36 -0
- package/build/src/frontends/java.d.ts +12 -0
- package/build/src/frontends/java.d.ts.map +1 -0
- package/build/src/frontends/java.js +630 -0
- package/build/src/frontends/javascript-typescript.d.ts +19 -0
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -0
- package/build/src/frontends/javascript-typescript.js +633 -0
- package/build/src/frontends/php.d.ts +12 -0
- package/build/src/frontends/php.d.ts.map +1 -0
- package/build/src/frontends/php.js +523 -0
- package/build/src/frontends/ruby.d.ts +12 -0
- package/build/src/frontends/ruby.d.ts.map +1 -0
- package/build/src/frontends/ruby.js +515 -0
- package/build/src/frontends/scalars.d.ts +19 -0
- package/build/src/frontends/scalars.d.ts.map +1 -0
- package/build/src/frontends/scalars.js +71 -0
- package/build/src/mapping.d.ts +160 -0
- package/build/src/mapping.d.ts.map +1 -0
- package/build/src/mapping.js +1120 -0
- package/build/src/semantic/location.d.ts +61 -0
- package/build/src/semantic/location.d.ts.map +1 -0
- package/build/src/semantic/location.js +142 -0
- package/build/src/semantic/operators.d.ts +16 -0
- package/build/src/semantic/operators.d.ts.map +1 -0
- package/build/src/semantic/operators.js +24 -0
- package/build/src/semantic/provenance.d.ts +74 -0
- package/build/src/semantic/provenance.d.ts.map +1 -0
- package/build/src/semantic/provenance.js +577 -0
- package/build/src/semantic/scalars.d.ts +19 -0
- package/build/src/semantic/scalars.d.ts.map +1 -0
- package/build/src/semantic/scalars.js +40 -0
- package/build/src/semantic/types.d.ts +1003 -0
- package/build/src/semantic/types.d.ts.map +1 -0
- package/build/src/semantic/types.js +279 -0
- package/build/src/semantic/validate.d.ts +60 -0
- package/build/src/semantic/validate.d.ts.map +1 -0
- package/build/src/semantic/validate.js +472 -0
- package/docs/architecture.md +39 -0
- package/docs/coding-standards.md +7 -0
- package/docs/goals.md +7 -0
- package/docs/language-support.md +69 -0
- package/docs/plans/2026-09-02-initial-toolchain.md +54 -0
- package/docs/source-maps.md +134 -0
- package/docs/testing.md +25 -0
- package/index.js +63 -0
- package/package.json +69 -0
- package/src/backends/identifiers.js +101 -0
- package/src/backends/index.js +159 -0
- package/src/backends/java.js +182 -0
- package/src/backends/javascript.js +184 -0
- package/src/backends/php.js +184 -0
- package/src/backends/ruby.js +163 -0
- package/src/backends/scalars.js +120 -0
- package/src/backends/shared.js +456 -0
- package/src/backends/typescript.js +168 -0
- package/src/backends/writer.js +224 -0
- package/src/diagnostic.js +103 -0
- package/src/frontends/index.js +36 -0
- package/src/frontends/java.js +735 -0
- package/src/frontends/javascript-typescript.js +718 -0
- package/src/frontends/php.js +593 -0
- package/src/frontends/ruby.js +622 -0
- package/src/frontends/scalars.js +77 -0
- package/src/mapping.js +1260 -0
- package/src/semantic/location.js +154 -0
- package/src/semantic/operators.js +28 -0
- package/src/semantic/provenance.js +629 -0
- package/src/semantic/scalars.js +44 -0
- package/src/semantic/types.js +319 -0
- package/src/semantic/validate.js +529 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Converts a source offset to a one-based point.
|
|
5
|
+
* @param {string} source - Complete source.
|
|
6
|
+
* @param {number} offset - Zero-based UTF-16 offset.
|
|
7
|
+
* @returns {import("./types.js").SourcePoint} Source point.
|
|
8
|
+
*/
|
|
9
|
+
export function pointAt(source, offset) {
|
|
10
|
+
if (!Number.isInteger(offset) || offset < 0 || offset > source.length) {
|
|
11
|
+
throw new RangeError(`Invalid source offset: ${offset}`)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let line = 1
|
|
15
|
+
let lineStart = 0
|
|
16
|
+
|
|
17
|
+
for (let index = 0; index < offset; index++) {
|
|
18
|
+
if (source[index] == "\r") {
|
|
19
|
+
if (source[index + 1] == "\n") {
|
|
20
|
+
if (index + 1 < offset) {
|
|
21
|
+
line++
|
|
22
|
+
index++
|
|
23
|
+
lineStart = index + 1
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
line++
|
|
27
|
+
lineStart = index + 1
|
|
28
|
+
}
|
|
29
|
+
} else if (source[index] == "\n") {
|
|
30
|
+
line++
|
|
31
|
+
lineStart = index + 1
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {column: offset - lineStart + 1, line, offset}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Builds a reusable UTF-16 line index in one pass.
|
|
40
|
+
* @param {string} source - Complete source.
|
|
41
|
+
* @returns {{source: string, lineStarts: number[]}} Coordinate index.
|
|
42
|
+
*/
|
|
43
|
+
export function createCoordinateIndex(source) {
|
|
44
|
+
const lineStarts = [0]
|
|
45
|
+
|
|
46
|
+
for (let index = 0; index < source.length; index++) {
|
|
47
|
+
if (source[index] == "\r") {
|
|
48
|
+
if (source[index + 1] == "\n") index++
|
|
49
|
+
lineStarts.push(index + 1)
|
|
50
|
+
} else if (source[index] == "\n") lineStarts.push(index + 1)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {lineStarts, source}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Converts an offset with a reusable coordinate index.
|
|
58
|
+
* @param {{source: string, lineStarts: number[]}} index - Coordinate index.
|
|
59
|
+
* @param {number} offset - Zero-based UTF-16 offset.
|
|
60
|
+
* @returns {import("./types.js").SourcePoint} Source point.
|
|
61
|
+
*/
|
|
62
|
+
export function indexedPointAt(index, offset) {
|
|
63
|
+
const {lineStarts, source} = index
|
|
64
|
+
|
|
65
|
+
if (!Number.isInteger(offset) || offset < 0 || offset > source.length) {
|
|
66
|
+
throw new RangeError(`Invalid source offset: ${offset}`)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let low = 0
|
|
70
|
+
let high = lineStarts.length
|
|
71
|
+
|
|
72
|
+
while (low < high) {
|
|
73
|
+
const middle = Math.floor((low + high) / 2)
|
|
74
|
+
|
|
75
|
+
if (lineStarts[middle] <= offset) low = middle + 1
|
|
76
|
+
else high = middle
|
|
77
|
+
}
|
|
78
|
+
const lineIndex = low - 1
|
|
79
|
+
|
|
80
|
+
return {column: offset - lineStarts[lineIndex] + 1, line: lineIndex + 1, offset}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Converts a canonical one-based UTF-16 line/column pair to its unique offset.
|
|
85
|
+
* @param {{source: string, lineStarts: number[]}} index - Coordinate index.
|
|
86
|
+
* @param {number} line - One-based line.
|
|
87
|
+
* @param {number} column - One-based UTF-16 column.
|
|
88
|
+
* @returns {number} Source offset.
|
|
89
|
+
*/
|
|
90
|
+
export function indexedOffsetAt(index, line, column) {
|
|
91
|
+
if (!Number.isInteger(line) || line < 1 || line > index.lineStarts.length || !Number.isInteger(column) || column < 1) {
|
|
92
|
+
throw new RangeError(`Invalid source position ${line}:${column}.`)
|
|
93
|
+
}
|
|
94
|
+
const offset = index.lineStarts[line - 1] + column - 1
|
|
95
|
+
const point = indexedPointAt(index, offset)
|
|
96
|
+
|
|
97
|
+
if (point.line != line || point.column != column) throw new RangeError(`Invalid source position ${line}:${column}.`)
|
|
98
|
+
|
|
99
|
+
return offset
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Converts a parser UTF-8 byte offset to Semantifold's UTF-16 source offset.
|
|
104
|
+
* @param {string} source - Complete source.
|
|
105
|
+
* @param {number} byteOffset - Zero-based UTF-8 byte offset.
|
|
106
|
+
* @returns {number} Zero-based UTF-16 offset.
|
|
107
|
+
*/
|
|
108
|
+
export function utf8ByteOffsetToUtf16Offset(source, byteOffset) {
|
|
109
|
+
if (!Number.isInteger(byteOffset) || byteOffset < 0) throw new RangeError(`Invalid UTF-8 source offset: ${byteOffset}`)
|
|
110
|
+
|
|
111
|
+
let bytes = 0
|
|
112
|
+
|
|
113
|
+
for (let index = 0; index < source.length;) {
|
|
114
|
+
if (bytes == byteOffset) return index
|
|
115
|
+
|
|
116
|
+
const codePoint = source.codePointAt(index)
|
|
117
|
+
|
|
118
|
+
if (codePoint === undefined) throw new RangeError(`Invalid UTF-8 source offset: ${byteOffset}`)
|
|
119
|
+
|
|
120
|
+
bytes += codePoint <= 0x7F ? 1 : codePoint <= 0x7FF ? 2 : codePoint <= 0xFFFF ? 3 : 4
|
|
121
|
+
if (bytes > byteOffset) throw new RangeError(`Invalid UTF-8 source offset: ${byteOffset}`)
|
|
122
|
+
index += codePoint > 0xFFFF ? 2 : 1
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (bytes == byteOffset) return source.length
|
|
126
|
+
|
|
127
|
+
throw new RangeError(`Invalid UTF-8 source offset: ${byteOffset}`)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Builds a normalized source location from offsets.
|
|
132
|
+
* @param {string} filename - Originating filename.
|
|
133
|
+
* @param {string} source - Complete source.
|
|
134
|
+
* @param {number} startOffset - Inclusive start offset.
|
|
135
|
+
* @param {number} endOffset - Exclusive end offset.
|
|
136
|
+
* @returns {import("./types.js").SourceLocation} Source location.
|
|
137
|
+
*/
|
|
138
|
+
export function locationFromOffsets(filename, source, startOffset, endOffset) {
|
|
139
|
+
return {
|
|
140
|
+
filename,
|
|
141
|
+
start: pointAt(source, startOffset),
|
|
142
|
+
end: pointAt(source, endOffset)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Builds a location spanning a complete source file.
|
|
148
|
+
* @param {string} filename - Originating filename.
|
|
149
|
+
* @param {string} source - Complete source.
|
|
150
|
+
* @returns {import("./types.js").SourceLocation} Source location.
|
|
151
|
+
*/
|
|
152
|
+
export function moduleLocation(filename, source) {
|
|
153
|
+
return locationFromOffsets(filename, source, 0, source.length)
|
|
154
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** @typedef {"Add" | "PhpAdd" | "Subtract" | "Multiply" | "Negate" | "Not" | "And" | "Or" | "Equal" | "NotEqual" | "JavaEqual" | "JavaNotEqual" | "StringEqual" | "StringNotEqual" | "StringConcat" | "LessThan" | "LessThanOrEqual" | "GreaterThan" | "GreaterThanOrEqual"} AdaptedOperation */
|
|
4
|
+
|
|
5
|
+
/** @type {WeakMap<object, AdaptedOperation>} */
|
|
6
|
+
const adaptedOperations = new WeakMap()
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Associates parser-normalized intent without adding it to a semantic value.
|
|
10
|
+
* @template {object} Expression
|
|
11
|
+
* @param {Expression} expression - Adapted expression awaiting type resolution.
|
|
12
|
+
* @param {AdaptedOperation} operation - Parser-normalized operation intent.
|
|
13
|
+
* @returns {Expression} The same expression.
|
|
14
|
+
*/
|
|
15
|
+
export function withAdaptedOperation(expression, operation) {
|
|
16
|
+
adaptedOperations.set(expression, operation)
|
|
17
|
+
|
|
18
|
+
return expression
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Reads private frontend intent during parsed-module validation.
|
|
23
|
+
* @param {object} expression - Adapted expression.
|
|
24
|
+
* @returns {AdaptedOperation | undefined} Associated operation.
|
|
25
|
+
*/
|
|
26
|
+
export function adaptedOperationFor(expression) {
|
|
27
|
+
return adaptedOperations.get(expression)
|
|
28
|
+
}
|