@fraczak/k 6.1.1 → 6.1.2
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/.codex +0 -0
- package/Code-derivation-tests/pattern-envelope.mjs +26 -0
- package/DOCS/REPL.md +33 -0
- package/DOCS/a.html +398 -0
- package/DOCS/dependency-graph.html +140 -0
- package/DOCS/dependency-graph.md +144 -0
- package/NAT.k~ +452 -0
- package/UU/ta.k +1 -0
- package/UU/ta.k~ +0 -0
- package/UU/tb.k +0 -0
- package/UU/tc.k +0 -0
- package/codecs/BINARY_FORMAT.html +471 -0
- package/codecs/POLYMORPHIC_BINARY_FORMAT.html +355 -0
- package/codecs/ieee.mjs +19 -4
- package/codecs/int.mjs +11 -4
- package/codecs/json.mjs +7 -4
- package/codecs/k-parse.mjs +7 -4
- package/codecs/k-print.mjs +7 -4
- package/codecs/runtime/cli-entry.mjs +13 -0
- package/codecs/show.mjs +7 -4
- package/codecs/unit.mjs +23 -8
- package/codecs/utf16.mjs +27 -5
- package/codecs/utf8.mjs +27 -5
- package/core.json +1 -0
- package/core.klib +1 -0
- package/core.klib~ +0 -0
- package/ieee.klib +1 -0
- package/k-vscode/package-lock.json +4176 -0
- package/kkk.k +197 -0
- package/kkk.klib +0 -0
- package/kkk.klib~ +0 -0
- package/p.json +5475 -0
- package/package.json +2 -2
- package/repl-codecs.mjs +173 -0
- package/repl.mjs +215 -5
- package/run.mjs +16 -2
- package/test-ieee-arithmetic.mjs +93 -0
- package/test-repl.mjs +60 -1
- package/tests.sh +10 -1
- package/type_registry/registry.mjs~ +105 -0
- package/type_registry/typeParser.jison~ +132 -0
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/copilot.data.migration.agent.xml +0 -6
- package/.idea/copilot.data.migration.ask.xml +0 -6
- package/.idea/copilot.data.migration.ask2agent.xml +0 -6
- package/.idea/copilot.data.migration.edit.xml +0 -6
- package/.idea/k.iml +0 -9
- package/.idea/misc.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
- package/k_compiler/runtime.c +0 -205
- package/k_compiler/runtime.h +0 -34
package/test-repl.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import assert from "node:assert";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
aliasNames,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
createState,
|
|
13
13
|
evaluateInput,
|
|
14
14
|
explicitSnippetTerminated,
|
|
15
|
+
helpText,
|
|
15
16
|
isMainEntrypoint,
|
|
16
17
|
lineHasExplicitContinuation,
|
|
17
18
|
lineTerminatesSnippet
|
|
@@ -61,6 +62,8 @@ assert(completions.includes(`(${state.typeAliases.nat}`));
|
|
|
61
62
|
|
|
62
63
|
completions = completeInput(":run su", state)[0];
|
|
63
64
|
assert(completions.includes(":run succ"));
|
|
65
|
+
completions = completeInput(":co", state)[0];
|
|
66
|
+
assert(completions.includes(":codec"));
|
|
64
67
|
|
|
65
68
|
completions = completeInput("$na", state)[0];
|
|
66
69
|
assert(completions.includes("$nat"));
|
|
@@ -89,6 +92,7 @@ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "k-repl-"));
|
|
|
89
92
|
const libPath = path.join(tmpDir, "session.klib");
|
|
90
93
|
const koPath = path.join(tmpDir, "succ.ko");
|
|
91
94
|
const sourcePath = path.join(tmpDir, "session.k");
|
|
95
|
+
const codecPath = path.join(tmpDir, "bool-codec.mjs");
|
|
92
96
|
const symlinkPath = path.resolve(".test-k-repl-link");
|
|
93
97
|
output = await evaluateInput(`:klib ${libPath}`, state);
|
|
94
98
|
assert.equal(output[0], `saved ${libPath}`);
|
|
@@ -117,6 +121,61 @@ assert.match(output[0], /^twice = \$nat succ succ \$nat; -- @/);
|
|
|
117
121
|
output = await evaluateInput(":C nat", loadedSource);
|
|
118
122
|
assert.match(output[0], /^\$ nat = < nat succ, @[^ ]+ zero >; -- @/);
|
|
119
123
|
|
|
124
|
+
const codecState = createState();
|
|
125
|
+
output = await evaluateInput(":type bool = <{} true, {} false>", codecState);
|
|
126
|
+
assert.match(output[0], /^\$ bool = @/);
|
|
127
|
+
const boolHash = codecState.typeAliases.bool;
|
|
128
|
+
const valueModuleUrl = pathToFileURL(path.resolve("Value.mjs")).href;
|
|
129
|
+
fs.writeFileSync(codecPath, `
|
|
130
|
+
import { Product, Variant } from ${JSON.stringify(valueModuleUrl)};
|
|
131
|
+
|
|
132
|
+
export const name = "yn";
|
|
133
|
+
export const codes = [${JSON.stringify(boolHash)}];
|
|
134
|
+
|
|
135
|
+
export function parse(text) {
|
|
136
|
+
const tag = text.trim();
|
|
137
|
+
if (tag !== "true" && tag !== "false") throw new Error("expected true or false");
|
|
138
|
+
return new Variant(tag, new Product({}));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function print(value) {
|
|
142
|
+
return value.tag;
|
|
143
|
+
}
|
|
144
|
+
`);
|
|
145
|
+
assert.match(helpText(), /:codec load file/);
|
|
146
|
+
output = await evaluateInput(":codec list", codecState);
|
|
147
|
+
assert.equal(output[0], "(none)");
|
|
148
|
+
completions = completeInput(":codec l", codecState)[0];
|
|
149
|
+
assert(completions.includes(":codec load"));
|
|
150
|
+
assert(completions.includes(":codec list"));
|
|
151
|
+
completions = completeInput(`:codec load ${tmpDir}/bool`, codecState)[0];
|
|
152
|
+
assert(completions.includes(`:codec load ${codecPath}`));
|
|
153
|
+
output = await evaluateInput(`:codec load ${codecPath}`, codecState);
|
|
154
|
+
assert.equal(output[0], `loaded codec yn for ${boolHash}`);
|
|
155
|
+
output = await evaluateInput(":codec list", codecState);
|
|
156
|
+
assert.match(output[0], new RegExp(`^yn ${boolHash.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`));
|
|
157
|
+
completions = completeInput(":input bo", codecState)[0];
|
|
158
|
+
assert(completions.includes(":input bool"));
|
|
159
|
+
completions = completeInput(":input bool y", codecState)[0];
|
|
160
|
+
assert(completions.includes(":input bool yn"));
|
|
161
|
+
output = await evaluateInput(":input bool yn", codecState);
|
|
162
|
+
assert.equal(output[0], `input ${boolHash} using yn: enter value text`);
|
|
163
|
+
output = await evaluateInput("true", codecState);
|
|
164
|
+
assert.match(output[0], /\{\}\|true \?</);
|
|
165
|
+
assert.match(output[0], /yn: true/);
|
|
166
|
+
output = await evaluateInput("{} | false", codecState);
|
|
167
|
+
assert.doesNotMatch(output[0], /yn: false/);
|
|
168
|
+
|
|
169
|
+
const utf8State = createState();
|
|
170
|
+
output = await evaluateInput(":load core.k", utf8State);
|
|
171
|
+
assert.equal(output[0], "loaded core.k");
|
|
172
|
+
output = await evaluateInput(":codec load ./codecs/utf8.mjs", utf8State);
|
|
173
|
+
assert.equal(output[0], `loaded codec utf8 for ${utf8State.typeAliases.string}`);
|
|
174
|
+
output = await evaluateInput(":input string utf8", utf8State);
|
|
175
|
+
assert.equal(output[0], `input ${utf8State.typeAliases.string} using utf8: enter value text`);
|
|
176
|
+
output = await evaluateInput("hello", utf8State);
|
|
177
|
+
assert.match(output[0], /utf8: hello/);
|
|
178
|
+
|
|
120
179
|
const replPath = fileURLToPath(new URL("./repl.mjs", import.meta.url));
|
|
121
180
|
try {
|
|
122
181
|
fs.rmSync(symlinkPath, { force: true });
|
package/tests.sh
CHANGED
|
@@ -11,5 +11,14 @@ node ./codecs/unit.mjs --parse | node ./codecs/unit.mjs --print | grep -qx '{}'
|
|
|
11
11
|
echo
|
|
12
12
|
printf 'A🙂\nBé~\t' | ./codecs/utf8.mjs --parse | ./k.mjs -k Examples/byte.k |./codecs/utf8.mjs --print
|
|
13
13
|
echo
|
|
14
|
-
|
|
14
|
+
./objects/compile-lib.mjs Examples/ieee.k ieee.klib
|
|
15
|
+
MUL=`./objects/extract-aliases.mjs ieee.klib | grep '^mul = @' | sed 's/^mul = \(@[^;]*\);.*$/\1/'`
|
|
16
|
+
DIV=`./objects/extract-aliases.mjs ieee.klib | grep '^div = @' | sed 's/^div = \(@[^;]*\);.*$/\1/'`
|
|
17
|
+
ARG=0.12
|
|
18
|
+
printf "$ARG * $ARG = "
|
|
19
|
+
echo $ARG | ./codecs/ieee.mjs --parse | ./k.mjs --lib ieee.klib "{()x,()y} $MUL .result" | ./codecs/ieee.mjs --print
|
|
20
|
+
printf "$ARG / $ARG = "
|
|
21
|
+
DIV_RESULT=`echo $ARG | ./codecs/ieee.mjs --parse | ./k.mjs --lib ieee.klib "{()x,()y} $DIV .result" | ./codecs/ieee.mjs --print`
|
|
22
|
+
echo "$DIV_RESULT"
|
|
23
|
+
test "$DIV_RESULT" = "1"
|
|
15
24
|
echo
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import http from 'http';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import codes from '../codes.mjs';
|
|
6
|
+
import { parse } from './typeParser.mjs';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const REGISTRY_FILE = path.join(__dirname, 'registry.json');
|
|
10
|
+
const PORT = 3001;
|
|
11
|
+
|
|
12
|
+
// Load existing registry if it exists
|
|
13
|
+
if (fs.existsSync(REGISTRY_FILE)) {
|
|
14
|
+
console.log('Loading existing registry...');
|
|
15
|
+
try {
|
|
16
|
+
const data = fs.readFileSync(REGISTRY_FILE, 'utf8');
|
|
17
|
+
const json = JSON.parse(data);
|
|
18
|
+
codes.load(json);
|
|
19
|
+
console.log(`Loaded ${Object.keys(json).length} types.`);
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.error('Error loading registry:', err);
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
console.log('No existing registry found. Starting fresh.');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const server = http.createServer((req, res) => {
|
|
28
|
+
// Helper to send JSON response
|
|
29
|
+
const sendJSON = (data, status = 200) => {
|
|
30
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
31
|
+
res.end(JSON.stringify(data));
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Helper to send Error
|
|
35
|
+
const sendError = (message, status = 400) => {
|
|
36
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
37
|
+
res.end(JSON.stringify({ error: message }));
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Route: POST
|
|
41
|
+
if (req.method === 'POST') {
|
|
42
|
+
let body = '';
|
|
43
|
+
req.on('data', chunk => {
|
|
44
|
+
body += chunk.toString();
|
|
45
|
+
});
|
|
46
|
+
req.on('end', () => {
|
|
47
|
+
try {
|
|
48
|
+
// 1. Parse the input string using the Jison parser
|
|
49
|
+
// The parser expects a string of type definitions
|
|
50
|
+
console.log("Received body:", body);
|
|
51
|
+
const definitions = parse(body);
|
|
52
|
+
console.log("Parsed definitions:", JSON.stringify(definitions, null, 2));
|
|
53
|
+
|
|
54
|
+
// 2. Register the parsed codes
|
|
55
|
+
// codes.register returns the representatives map { temp_name: canonical_hash }
|
|
56
|
+
const representatives = codes.register(definitions);
|
|
57
|
+
|
|
58
|
+
// Filter out generated names (_gen_...) and canonical names (@...)
|
|
59
|
+
const filteredRepresentatives = Object.fromEntries(
|
|
60
|
+
Object.entries(representatives).filter(([key, value]) =>
|
|
61
|
+
!key.startsWith('_gen_') && !key.startsWith('@')
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// 3. Save to disk
|
|
66
|
+
const dump = codes.dump();
|
|
67
|
+
fs.writeFileSync(REGISTRY_FILE, JSON.stringify(dump, null, 2));
|
|
68
|
+
|
|
69
|
+
// 4. Return the mapping
|
|
70
|
+
sendJSON(filteredRepresentatives);
|
|
71
|
+
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.error(err);
|
|
74
|
+
sendError(`Registration failed: ${err.message}`);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// Route: GET
|
|
79
|
+
else if (req.method === 'GET') {
|
|
80
|
+
const typeId = req.url.split('/').pop();
|
|
81
|
+
console.log("Requested type ID:", typeId);
|
|
82
|
+
if (!typeId) {
|
|
83
|
+
sendError('Missing type ID');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Decode URI component in case @ is encoded
|
|
87
|
+
const decodedId = decodeURIComponent(typeId);
|
|
88
|
+
console.log("Decoded type ID:", decodedId);
|
|
89
|
+
|
|
90
|
+
const typeDef = codes.find(decodedId);
|
|
91
|
+
if (typeDef.code === 'undefined') {
|
|
92
|
+
sendError('Type not found', 404);
|
|
93
|
+
} else {
|
|
94
|
+
sendJSON(typeDef);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// 404 Not Found
|
|
98
|
+
else {
|
|
99
|
+
sendError('Not Found', 404);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
server.listen(PORT, () => {
|
|
104
|
+
console.log(`Type Registry running at http://localhost:${PORT}/`);
|
|
105
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
%{
|
|
2
|
+
|
|
3
|
+
let defs = {};
|
|
4
|
+
let genCount = 0;
|
|
5
|
+
let genNameId;
|
|
6
|
+
|
|
7
|
+
function genName() {
|
|
8
|
+
return `_gen_${genCount++}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function fromEscString(escString) {
|
|
12
|
+
const isSingleQuoted = escString.startsWith("'");
|
|
13
|
+
let str = escString.substring(1, escString.length - 1);
|
|
14
|
+
if (isSingleQuoted) {
|
|
15
|
+
str = str.replace(/\\'/g, "'");
|
|
16
|
+
} else {
|
|
17
|
+
str = str.replace(/\\"/g, '"');
|
|
18
|
+
}
|
|
19
|
+
str = str.replace(/\\\\/g, '\\');
|
|
20
|
+
str = str.replace(/\\\//g, '/');
|
|
21
|
+
str = str.replace(/\\b/g, '\b');
|
|
22
|
+
str = str.replace(/\\f/g, '\f');
|
|
23
|
+
str = str.replace(/\\n/g, '\n');
|
|
24
|
+
str = str.replace(/\\r/g, '\r');
|
|
25
|
+
str = str.replace(/\\t/g, '\t');
|
|
26
|
+
str = str.replace(/\\u([\dA-F]{4})/gi, (match, p1) => String.fromCharCode(parseInt(p1, 16)));
|
|
27
|
+
|
|
28
|
+
return str;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
%}
|
|
32
|
+
|
|
33
|
+
%lex
|
|
34
|
+
|
|
35
|
+
%%
|
|
36
|
+
\s+ /* blanks */
|
|
37
|
+
"<" return 'LA';
|
|
38
|
+
">" return 'RA';
|
|
39
|
+
"{" return 'LC';
|
|
40
|
+
"}" return 'RC';
|
|
41
|
+
"=" return 'EQ';
|
|
42
|
+
"," return 'COMMA';
|
|
43
|
+
";" return 'SC';
|
|
44
|
+
"@" return 'AT';
|
|
45
|
+
"$" return 'DOLLAR';
|
|
46
|
+
\"([^"\\]|\\(.|\n))*\"|\'([^'\\]|\\(.|\n))*\' return 'STRING';
|
|
47
|
+
[a-zA-Z0-9_+-][a-zA-Z0-9_?!+-]* return 'NAME';
|
|
48
|
+
<<EOF>> return 'EOF';
|
|
49
|
+
. return 'INVALID';
|
|
50
|
+
|
|
51
|
+
/lex
|
|
52
|
+
|
|
53
|
+
%token NAME STRING
|
|
54
|
+
%token LA RA LC RC EQ COMMA SC AT DOLLAR
|
|
55
|
+
%token EOF
|
|
56
|
+
|
|
57
|
+
%start expressions
|
|
58
|
+
|
|
59
|
+
%%
|
|
60
|
+
|
|
61
|
+
expressions
|
|
62
|
+
: initialize_defs definitions EOF
|
|
63
|
+
{ return defs; }
|
|
64
|
+
;
|
|
65
|
+
|
|
66
|
+
initialize_defs
|
|
67
|
+
: /* empty */
|
|
68
|
+
{ defs = {}; genCount = 0; }
|
|
69
|
+
;
|
|
70
|
+
|
|
71
|
+
definitions
|
|
72
|
+
: definition
|
|
73
|
+
| definitions definition
|
|
74
|
+
;
|
|
75
|
+
|
|
76
|
+
definition
|
|
77
|
+
: DOLLAR name EQ LA field_list RA SC
|
|
78
|
+
{ defs[$2] = { code: 'union', union: $5 }; }
|
|
79
|
+
| DOLLAR name EQ LC field_list RC SC
|
|
80
|
+
{ defs[$2] = { code: 'product', product: $5 }; }
|
|
81
|
+
;
|
|
82
|
+
|
|
83
|
+
type_expr
|
|
84
|
+
: LA field_list RA
|
|
85
|
+
{
|
|
86
|
+
genNameId = genName();
|
|
87
|
+
defs[genNameId] = { code: 'union', union: $2 };
|
|
88
|
+
$$ = genNameId;
|
|
89
|
+
}
|
|
90
|
+
| LC field_list RC
|
|
91
|
+
{
|
|
92
|
+
genNameId = genName();
|
|
93
|
+
defs[genNameId] = { code: 'product', product: $2 };
|
|
94
|
+
$$ = genNameId;
|
|
95
|
+
}
|
|
96
|
+
| ref
|
|
97
|
+
{ $$ = $1; }
|
|
98
|
+
;
|
|
99
|
+
|
|
100
|
+
ref
|
|
101
|
+
: name
|
|
102
|
+
{ $$ = $1; }
|
|
103
|
+
| AT name
|
|
104
|
+
{ $$ = '@' + $2; }
|
|
105
|
+
;
|
|
106
|
+
|
|
107
|
+
field_list
|
|
108
|
+
: /* empty */
|
|
109
|
+
{ $$ = {}; }
|
|
110
|
+
| field
|
|
111
|
+
{ $$ = {}; $$[$1.label] = $1.type; }
|
|
112
|
+
| field_list COMMA field
|
|
113
|
+
{ $$ = $1; $$[$3.label] = $3.type; }
|
|
114
|
+
;
|
|
115
|
+
|
|
116
|
+
field
|
|
117
|
+
: type_expr label
|
|
118
|
+
{ $$ = { type: $1, label: $2 }; }
|
|
119
|
+
;
|
|
120
|
+
|
|
121
|
+
label
|
|
122
|
+
: name
|
|
123
|
+
{ $$ = $1; }
|
|
124
|
+
| str
|
|
125
|
+
{ $$ = $1; }
|
|
126
|
+
;
|
|
127
|
+
|
|
128
|
+
name: NAME { $$ = yytext; };
|
|
129
|
+
str: STRING { $$ = fromEscString(yytext); };
|
|
130
|
+
|
|
131
|
+
%%
|
|
132
|
+
|
package/.idea/k.iml
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<module type="JAVA_MODULE" version="4">
|
|
3
|
-
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
4
|
-
<exclude-output />
|
|
5
|
-
<content url="file://$MODULE_DIR$" />
|
|
6
|
-
<orderEntry type="inheritedJdk" />
|
|
7
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
8
|
-
</component>
|
|
9
|
-
</module>
|
package/.idea/misc.xml
DELETED
package/.idea/modules.xml
DELETED
package/.idea/vcs.xml
DELETED
package/k_compiler/runtime.c
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
#include "runtime.h"
|
|
2
|
-
|
|
3
|
-
#include <stdio.h>
|
|
4
|
-
#include <stdlib.h>
|
|
5
|
-
#include <string.h>
|
|
6
|
-
|
|
7
|
-
typedef enum {
|
|
8
|
-
K_NODE_PRODUCT = 1,
|
|
9
|
-
K_NODE_VARIANT = 2
|
|
10
|
-
} KNodeKind;
|
|
11
|
-
|
|
12
|
-
typedef struct {
|
|
13
|
-
const char *label;
|
|
14
|
-
KValue value;
|
|
15
|
-
} KField;
|
|
16
|
-
|
|
17
|
-
struct KNode {
|
|
18
|
-
KNodeKind kind;
|
|
19
|
-
const char *type_id;
|
|
20
|
-
union {
|
|
21
|
-
struct {
|
|
22
|
-
int field_count;
|
|
23
|
-
KField *fields;
|
|
24
|
-
} product;
|
|
25
|
-
struct {
|
|
26
|
-
const char *tag;
|
|
27
|
-
KValue child;
|
|
28
|
-
} variant;
|
|
29
|
-
} as;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
static char *krt_strdup(const char *value) {
|
|
33
|
-
size_t len = strlen(value);
|
|
34
|
-
char *result = (char *)malloc(len + 1);
|
|
35
|
-
memcpy(result, value, len + 1);
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static const char *krt_infer_variant_type(const char *label, KValue child) {
|
|
40
|
-
if (child == NULL) return "";
|
|
41
|
-
if (child->type_id != NULL && child->type_id[0] != '\0') {
|
|
42
|
-
return child->type_id;
|
|
43
|
-
}
|
|
44
|
-
if (strcmp(label, "zero") == 0 || strcmp(label, "succ") == 0) {
|
|
45
|
-
return "@w8iSHeQQE738vEmWNGja3FQWk3XuExQKZ2pbm8ApEdkF";
|
|
46
|
-
}
|
|
47
|
-
return "";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
static KOpt krt_ok(KValue value) {
|
|
51
|
-
KOpt result;
|
|
52
|
-
result.ok = 1;
|
|
53
|
-
result.value = value;
|
|
54
|
-
return result;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
static const char *json_extract_string(const char *json, const char *key) {
|
|
58
|
-
static char buffer[256];
|
|
59
|
-
char pattern[64];
|
|
60
|
-
const char *cursor;
|
|
61
|
-
const char *start;
|
|
62
|
-
size_t length = 0;
|
|
63
|
-
|
|
64
|
-
snprintf(pattern, sizeof(pattern), "\"%s\":\"", key);
|
|
65
|
-
cursor = strstr(json, pattern);
|
|
66
|
-
if (cursor == NULL) return NULL;
|
|
67
|
-
start = cursor + strlen(pattern);
|
|
68
|
-
|
|
69
|
-
while (start[length] != '\0' && start[length] != '"') {
|
|
70
|
-
if (start[length] == '\\' && start[length + 1] != '\0') {
|
|
71
|
-
length += 2;
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
length += 1;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (length >= sizeof(buffer)) {
|
|
78
|
-
length = sizeof(buffer) - 1;
|
|
79
|
-
}
|
|
80
|
-
memcpy(buffer, start, length);
|
|
81
|
-
buffer[length] = '\0';
|
|
82
|
-
return buffer;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
static KValue product_field(KValue input, const char *label) {
|
|
86
|
-
int index;
|
|
87
|
-
if (input == NULL || input->kind != K_NODE_PRODUCT) return NULL;
|
|
88
|
-
for (index = 0; index < input->as.product.field_count; index += 1) {
|
|
89
|
-
if (strcmp(input->as.product.fields[index].label, label) == 0) {
|
|
90
|
-
return input->as.product.fields[index].value;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return NULL;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
KOpt krt_fail(void) {
|
|
97
|
-
KOpt result;
|
|
98
|
-
result.ok = 0;
|
|
99
|
-
result.value = NULL;
|
|
100
|
-
return result;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
KOpt krt_return_input(KValue input) {
|
|
104
|
-
return krt_ok(input);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
KValue krt_new_product(const char *type_id, int field_count, const char *const *labels, KValue const *values) {
|
|
108
|
-
int index;
|
|
109
|
-
KNode *node = (KNode *)calloc(1, sizeof(KNode));
|
|
110
|
-
node->kind = K_NODE_PRODUCT;
|
|
111
|
-
node->type_id = krt_strdup(type_id == NULL ? "" : type_id);
|
|
112
|
-
node->as.product.field_count = field_count;
|
|
113
|
-
node->as.product.fields = field_count > 0 ? (KField *)calloc((size_t)field_count, sizeof(KField)) : NULL;
|
|
114
|
-
|
|
115
|
-
for (index = 0; index < field_count; index += 1) {
|
|
116
|
-
node->as.product.fields[index].label = krt_strdup(labels[index]);
|
|
117
|
-
node->as.product.fields[index].value = values[index];
|
|
118
|
-
}
|
|
119
|
-
return node;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
KValue krt_new_variant(const char *type_id, const char *label, KValue child) {
|
|
123
|
-
KNode *node = (KNode *)calloc(1, sizeof(KNode));
|
|
124
|
-
node->kind = K_NODE_VARIANT;
|
|
125
|
-
node->type_id = krt_strdup(type_id == NULL ? "" : type_id);
|
|
126
|
-
node->as.variant.tag = krt_strdup(label);
|
|
127
|
-
node->as.variant.child = child;
|
|
128
|
-
return node;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
KOpt krt_guard_code(KValue input, const char *type_id) {
|
|
132
|
-
if (input == NULL) return krt_fail();
|
|
133
|
-
if (type_id == NULL || type_id[0] == '\0') return krt_ok(input);
|
|
134
|
-
if (strcmp(input->type_id, type_id) == 0) return krt_ok(input);
|
|
135
|
-
return krt_fail();
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
KOpt krt_guard_type_var(KValue input, const char *var_name) {
|
|
139
|
-
(void)var_name;
|
|
140
|
-
if (input == NULL) return krt_fail();
|
|
141
|
-
return krt_ok(input);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
KOpt krt_guard_shape(KValue input, const char *shape_descriptor_json) {
|
|
145
|
-
const char *shape;
|
|
146
|
-
if (input == NULL) return krt_fail();
|
|
147
|
-
shape = json_extract_string(shape_descriptor_json, "shape");
|
|
148
|
-
if (shape == NULL || strcmp(shape, "any") == 0) return krt_ok(input);
|
|
149
|
-
if (strcmp(shape, "product") == 0 && input->kind == K_NODE_PRODUCT) return krt_ok(input);
|
|
150
|
-
if (strcmp(shape, "union") == 0 && input->kind == K_NODE_VARIANT) return krt_ok(input);
|
|
151
|
-
return krt_fail();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
KOpt krt_project_field(KValue input, const char *projection_descriptor_json) {
|
|
155
|
-
const char *label = json_extract_string(projection_descriptor_json, "label");
|
|
156
|
-
KValue child = product_field(input, label);
|
|
157
|
-
if (label == NULL || child == NULL) return krt_fail();
|
|
158
|
-
return krt_ok(child);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
KOpt krt_project_variant(KValue input, const char *projection_descriptor_json) {
|
|
162
|
-
const char *label = json_extract_string(projection_descriptor_json, "label");
|
|
163
|
-
if (label == NULL || input == NULL || input->kind != K_NODE_VARIANT) return krt_fail();
|
|
164
|
-
if (strcmp(input->as.variant.tag, label) != 0) return krt_fail();
|
|
165
|
-
return krt_ok(input->as.variant.child);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
KOpt krt_make_product(const char *type_id, int field_count, const char *const *labels, KValue const *values) {
|
|
169
|
-
return krt_ok(krt_new_product(type_id, field_count, labels, values));
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
KOpt krt_make_variant(KValue child, const char *label, const char *type_id) {
|
|
173
|
-
const char *resolved_type = type_id;
|
|
174
|
-
if (resolved_type == NULL || resolved_type[0] == '\0') {
|
|
175
|
-
resolved_type = krt_infer_variant_type(label, child);
|
|
176
|
-
}
|
|
177
|
-
return krt_ok(krt_new_variant(resolved_type, label, child));
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
void krt_print_value(KValue value) {
|
|
181
|
-
int index;
|
|
182
|
-
if (value == NULL) {
|
|
183
|
-
printf("<null>");
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (value->kind == K_NODE_PRODUCT) {
|
|
188
|
-
if (value->as.product.field_count == 0) {
|
|
189
|
-
printf("{}");
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
printf("{");
|
|
193
|
-
for (index = 0; index < value->as.product.field_count; index += 1) {
|
|
194
|
-
if (index > 0) printf(", ");
|
|
195
|
-
printf("%s:", value->as.product.fields[index].label);
|
|
196
|
-
krt_print_value(value->as.product.fields[index].value);
|
|
197
|
-
}
|
|
198
|
-
printf("}");
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
printf("%s(", value->as.variant.tag);
|
|
203
|
-
krt_print_value(value->as.variant.child);
|
|
204
|
-
printf(")");
|
|
205
|
-
}
|
package/k_compiler/runtime.h
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
#ifndef K_COMPILER_RUNTIME_H
|
|
2
|
-
#define K_COMPILER_RUNTIME_H
|
|
3
|
-
|
|
4
|
-
#ifdef __cplusplus
|
|
5
|
-
extern "C" {
|
|
6
|
-
#endif
|
|
7
|
-
|
|
8
|
-
typedef struct KNode KNode;
|
|
9
|
-
typedef KNode *KValue;
|
|
10
|
-
|
|
11
|
-
typedef struct {
|
|
12
|
-
int ok;
|
|
13
|
-
KValue value;
|
|
14
|
-
} KOpt;
|
|
15
|
-
|
|
16
|
-
KOpt krt_fail(void);
|
|
17
|
-
KOpt krt_return_input(KValue input);
|
|
18
|
-
KOpt krt_guard_code(KValue input, const char *type_id);
|
|
19
|
-
KOpt krt_guard_type_var(KValue input, const char *var_name);
|
|
20
|
-
KOpt krt_guard_shape(KValue input, const char *shape_descriptor_json);
|
|
21
|
-
KOpt krt_project_field(KValue input, const char *projection_descriptor_json);
|
|
22
|
-
KOpt krt_project_variant(KValue input, const char *projection_descriptor_json);
|
|
23
|
-
KOpt krt_make_product(const char *type_id, int field_count, const char *const *labels, KValue const *values);
|
|
24
|
-
KOpt krt_make_variant(KValue child, const char *label, const char *type_id);
|
|
25
|
-
|
|
26
|
-
KValue krt_new_product(const char *type_id, int field_count, const char *const *labels, KValue const *values);
|
|
27
|
-
KValue krt_new_variant(const char *type_id, const char *label, KValue child);
|
|
28
|
-
void krt_print_value(KValue value);
|
|
29
|
-
|
|
30
|
-
#ifdef __cplusplus
|
|
31
|
-
}
|
|
32
|
-
#endif
|
|
33
|
-
|
|
34
|
-
#endif
|