diff options
author | Minteck <contact@minteck.org> | 2022-12-02 22:03:58 +0100 |
---|---|---|
committer | Minteck <contact@minteck.org> | 2022-12-02 22:03:58 +0100 |
commit | f08a7afcc73bb5bd4ebab40e124dc8e56fc3960f (patch) | |
tree | 21bd91a35edf316a89e1cb02d6b0b1c6ddae4692 | |
parent | 07560d746f6bf18c3e349cac89832d2a22996709 (diff) | |
download | wing-f08a7afcc73bb5bd4ebab40e124dc8e56fc3960f.tar.gz wing-f08a7afcc73bb5bd4ebab40e124dc8e56fc3960f.tar.bz2 wing-f08a7afcc73bb5bd4ebab40e124dc8e56fc3960f.zip |
Conditions and other fixes
-rw-r--r-- | .idea/vcs.xml | 6 | ||||
-rw-r--r-- | conditions/defined.js | 7 | ||||
-rw-r--r-- | demo.wing | 1 | ||||
-rw-r--r-- | functions/print.js | 4 | ||||
-rw-r--r-- | index.js | 240 | ||||
-rwxr-xr-x | test.wing | 25 | ||||
-rw-r--r-- | test.wjs | 1 |
7 files changed, 226 insertions, 58 deletions
diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project>
\ No newline at end of file diff --git a/conditions/defined.js b/conditions/defined.js new file mode 100644 index 0000000..2bf1f3e --- /dev/null +++ b/conditions/defined.js @@ -0,0 +1,7 @@ +WingAPI.createCondition("defined", [ + { + type: "variable" + } +], (parameters) => { + return Object.keys(variables).includes(parameters[0]); +})
\ No newline at end of file diff --git a/demo.wing b/demo.wing new file mode 100644 index 0000000..84975b3 --- /dev/null +++ b/demo.wing @@ -0,0 +1 @@ +print Imported file!
\ No newline at end of file diff --git a/functions/print.js b/functions/print.js new file mode 100644 index 0000000..290eea4 --- /dev/null +++ b/functions/print.js @@ -0,0 +1,4 @@ +WingAPI.createFunction("print", true, (parameter) => { + console.log(parameter); +}) + @@ -1,5 +1,6 @@ const fs = require('fs'); const chalk = require('chalk'); +const path = require('path'); global._debug = false; if (!process.argv[2]) { @@ -13,6 +14,7 @@ if (!fs.existsSync(process.argv[2])) { } let file; +let filename = path.resolve(process.argv[2]); try { file = fs.readFileSync(process.argv[2]).toString(); @@ -21,37 +23,139 @@ try { process.exit(2); } -let variables = {}; -let functions = { - print: (parameters) => { - console.log(parameters); +global.variables = {}; +global.functions = {}; +global.conditions = {}; +global.operators = {}; + +global.WingAPI = { + createFunction: (name, parameter, runtime) => { + functions[name] = { + parameter, + runtime + } + }, + createCondition: (name, parameters, runtime) => { + conditions[name] = { + parameters, + runtime + } } -}; +} + +process.chdir(__dirname); + +for (let file of fs.readdirSync("./functions")) { + require(__dirname + "/functions/" + file); +} + +for (let file of fs.readdirSync("./conditions")) { + require(__dirname + "/conditions/" + file); +} + let lines = file.replaceAll("\r\n", "\n").split("\n"); let contexts = []; -interpret(lines); +interpret(lines, undefined, null, filename); + +function evaluateCondition(condition, variables, functions, contexts, index, globalLines, currentFunction, lines, file) { + let argv = condition.split(" "); + let name = argv[0]; + argv.shift(); let params = argv; + + if (conditions[name]) { + for (let index in conditions[name]["parameters"]) { + let parameter = conditions[name]["parameters"][index]; + let local = params[index]; + + if (params[index]) { + switch (parameter.type) { + case "variable": + if (local.match(/^\$([a-zA-Z0-9-_]+)$/gm)) { + params[index] = params[index].substring(1); + } else { + error("Syntax error", index, globalLines, currentFunction, lines, file); + return false; + } + + break; + + case "number": + if (!isNaN(parseFloat(local)) && isFinite(local)) { + params[index] = parseFloat(local); + } else { + error("Syntax error", index, globalLines, currentFunction, lines, file); + return false; + } + + break; -function evaluateCondition(condition, variables, functions, contexts, index) { - return true; + case "values": + if (parameter.values.includes(local)) { + params[index] = local; + } else { + error("Syntax error", index, globalLines, currentFunction, lines, file); + return false; + } + + break; + + default: + throw new Error("Invalid condition parameter type"); + } + } else { + error("Missing parameter for condition " + name, index, globalLines, currentFunction, lines, file); + return false; + } + } + + return conditions[name]["runtime"](params); + } else { + error("Unresolved reference (condition " + name + ")", index, globalLines, currentFunction, lines, file); + return false; + } } -function error(message, line, globalLine, currentFunction, lines) { +function error(message, line, globalLine, currentFunction, lines, filename) { + console.log(chalk.gray("------------------------------------------------------------------------")); + if (line === globalLine) { - console.error(chalk.blueBright.inverse("Wing:") + " " + chalk.yellow(message + ", at line " + chalk.magenta(line))); + console.error(chalk.blueBright.inverse("Wing:") + " " + chalk.yellow(message + "\n * at line " + chalk.magenta(line) + "\n * in file " + chalk.magenta(filename))); } else { if (currentFunction) { - console.error(chalk.blueBright.inverse("Wing:") + " " + chalk.yellow(message + ", at line " + chalk.magenta(line + "@" + currentFunction + " < " + globalLine))); + console.error(chalk.blueBright.inverse("Wing:") + " " + chalk.yellow(message + "\n * at local line " + chalk.magenta(line) + ", global line " + chalk.magenta(globalLine + 1) + "\n * in function " + chalk.magenta(currentFunction) + "\n * in file " + chalk.magenta(filename))); } else { - console.error(chalk.blueBright.inverse("Wing:") + " " + chalk.yellow(message + ", at line " + chalk.magenta(line + " < " + globalLine))); + console.error(chalk.blueBright.inverse("Wing:") + " " + chalk.yellow(message + "\n * at local line " + chalk.magenta(line) + ", global line " + chalk.magenta(globalLine + 1) + "\n * in file " + chalk.magenta(filename))); + } + + if (currentFunction) { + globalLine++; } } + + let lns = [(globalLine - 1).toString().length, globalLine.toString().length, (globalLine + 1).toString().length].reduce((a, b) => a.length > b.length ? a : b, '').length; + + console.log(""); + + if (lines[line - 2] || typeof lines[line - 2] === "string") { + let lnp = " ".repeat(lns - (globalLine - 1).toString().length) + (globalLine - 1).toString(); + console.log(" " + chalk.gray(lnp + " ") + chalk.gray(lines[line - 2])); + } + + console.log(chalk.blueBright.bold(">") + " " + chalk.gray(globalLine + " ") + lines[line - 1]); + + if (lines[line] || typeof lines[line] === "string") { + let lnn = " ".repeat(lns - (globalLine + 1).toString().length) + (globalLine + 1).toString(); + console.log(" " + chalk.gray(lnn + " ") + chalk.gray(lines[line])); + } + + console.log(chalk.gray("------------------------------------------------------------------------")); } -function interpret(lines, globalLines, currentFunction) { +function interpret(lines, globalLines, currentFunction, file) { let count = lines.length; - lines = lines.map(i => i.trim()).filter(i => i !== "" && !i.startsWith("--") && !i.startsWith("#!")); + lines = lines.map(i => i.trim()); let stripped = count - lines.length; let index = 1; @@ -65,7 +169,8 @@ function interpret(lines, globalLines, currentFunction) { try { let currentContext = contexts[contexts.length - 1]; - line = line.split("--")[0]; + line = !line.trim().startsWith("--") ? line.split("--")[0] : line; + if (_debug) console.log("--> " + index + "; " + globalLines); if (_debug) console.log("--> " + line); if (_debug) console.log("-->", contexts); @@ -79,7 +184,7 @@ function interpret(lines, globalLines, currentFunction) { } else { let condition = /^if (.+) do$/m.exec(line)[1]; - if (!evaluateCondition(condition, variables, functions, contexts, index)) { + if (!evaluateCondition(condition, variables, functions, contexts, index, globalLines, currentFunction, lines, file)) { contexts.push({ type: "unmatched", target: null @@ -123,7 +228,7 @@ function interpret(lines, globalLines, currentFunction) { if (_debug) console.log("-------------------"); continue; } else { - error("Attempted to use 'else' while not in a condition context", index, globalLines, currentFunction, lines); + error("Attempted to use 'else' while not in a condition context", index, globalLines, currentFunction, lines, file); } } } @@ -136,7 +241,7 @@ function interpret(lines, globalLines, currentFunction) { contexts.pop(); } else { - error("Attempted to leave primary context", index, globalLines, currentFunction, lines); + error("Attempted to leave primary context", index, globalLines, currentFunction, lines, file); } index++; globalLines++; @@ -157,16 +262,35 @@ function interpret(lines, globalLines, currentFunction) { continue; } - if (line.match(/^\$([a-zA-Z0-9-_]+) *= *(.*)$/gm)) { + if (line.trim() === "" || line.trim().startsWith("--") || line.trim().startsWith("#!")) { + index++; + globalLines++; + if (_debug) console.log("-------------------"); + continue; + } else if (line.match(/^\$([a-zA-Z0-9-_]+) *= *(.*)$/gm)) { let name = /\$([a-zA-Z0-9-_]+) *= *(.*)/gm.exec(line)[1]; variables[name] = /\$([a-zA-Z0-9-_]+) *= *(.*)/gm.exec(line)[2]; - } else if (line.match(/^@([a-zA-Z0-9-_]+)( (.*)|)$/gm)) { + } else if (line.match(/^function ([a-zA-Z0-9-_]+)( (\$([a-zA-Z0-9-_]+))*)?$/m)) { + let match = /^function ([a-zA-Z0-9-_]+)( (\$([a-zA-Z0-9-_]+))*)?$/m.exec(line); + let name = match[1]; + let parameter = match[4]; + contexts.push({ + type: "function", + target: name + }); + + if (parameter) { + functions[name] = "@@$" + parameter + "\n@@" + index + "\n"; + } else { + functions[name] = "@@\n@@" + index + "\n"; + } + } else if (line.match(/^([a-zA-Z0-9-_]+)( (.*)|)$/gm)) { let execute = true; - let func = /@([a-zA-Z0-9-_]+)( (.*)|)/gm.exec(line)[1]; - let parameters = /@([a-zA-Z0-9-_]+)( (.*)|)/gm.exec(line)[3]; + let func = /([a-zA-Z0-9-_]+)( (.*)|)/gm.exec(line)[1]; + let parameters = /([a-zA-Z0-9-_]+)( (.*)|)/gm.exec(line)[3]; if (!Object.keys(functions).includes(func)) { - error("Unresolved reference (@" + func + ")", index, globalLines, currentFunction, lines); + error("Unresolved reference (function " + func + ")", index, globalLines, currentFunction, lines, file); } if (parameters) { @@ -175,7 +299,7 @@ function interpret(lines, globalLines, currentFunction) { let name = vars[1]; if (!Object.keys(variables).includes(name)) { - error("Unresolved reference ($" + name + ")", index, globalLines, currentFunction, lines); + error("Unresolved reference ($" + name + ")", index, globalLines, currentFunction, lines, file); execute = false; break; } @@ -187,11 +311,17 @@ function interpret(lines, globalLines, currentFunction) { } if (execute) { - if (typeof functions[func] === "function") { - functions[func](parameters, variables, functions, contexts, index, globalLines, currentFunction, lines); + if (typeof functions[func] === "object") { + if (functions[func]["parameter"] && !parameters) { + error("Missing parameter for function " + func, index, globalLines, currentFunction, lines, file); + } else if (!functions[func]["parameter"] && parameters) { + error("Function " + func + " does not admit a parameter", index, globalLines, currentFunction, lines, file); + } + + functions[func]["runtime"](parameters, variables, functions, contexts, index, globalLines, currentFunction, lines, file); } else { let lines = functions[func].split("\n"); - let initialIndex = lines[1].substring(2); + let initialIndex = parseInt(lines[1].substring(2)); if (parameters && lines[0].startsWith("@@$")) { let parameter = lines[0].substring(3); @@ -199,38 +329,62 @@ function interpret(lines, globalLines, currentFunction) { lines.shift(); lines.shift(); - interpret(lines, initialIndex, func); + interpret(lines, initialIndex, func, file); } else if (parameters) { - error("Function @" + func + " does not admit a parameter", index, globalLines, currentFunction, lines); + error("Function " + func + " does not admit a parameter", index, globalLines, currentFunction, lines, file); + } else if (lines[0].startsWith("@@$")) { + error("Missing parameter for function " + func, index, globalLines, currentFunction, lines, file); } else { lines.shift(); lines.shift(); - interpret(lines, initialIndex, func); + interpret(lines, initialIndex, func, file); } } } - } else if (line.match(/^function @([a-zA-Z0-9-_]+)( (\$([a-zA-Z0-9-_]+))*)?$/m)) { - let match = /^function @([a-zA-Z0-9-_]+)( (\$([a-zA-Z0-9-_]+))*)?$/m.exec(line); - let name = match[1]; - let parameter = match[4]; - contexts.push({ - type: "function", - target: name - }); + } else if (line.startsWith("#")) { + process.chdir(path.dirname(file)); - if (parameter) { - functions[name] = "@@$" + parameter + "\n@@" + index + "\n"; + if (currentFunction) { + error("Attempted to import from a function context", index, globalLines, currentFunction, lines, file); + index++; + globalLines++; + continue; + } + + let importFile = line.substring(1); + + if (!fs.existsSync(importFile)) { + error("Imported file " + importFile + " not found", index, globalLines, currentFunction, lines, file); + index++; globalLines++; continue; + } + + try { + let _text = fs.readFileSync(importFile).toString(); + } catch (e) { + error("Imported file " + importFile + " is unreadable", index, globalLines, currentFunction, lines, file); + index++; + globalLines++; + continue; + } + + let ext = path.extname(importFile); + + if (ext === ".wjs") { + eval(fs.readFileSync(importFile).toString()); + } else if (ext === ".wing") { + interpret(fs.readFileSync(importFile).toString().replaceAll("\r\n", "\n").split("\n"), undefined, null, importFile); } else { - functions[name] = "@@\n@@" + index + "\n"; + error("Imported file " + importFile + " is neither of Wing JS Binding file (.wjs) or Wing Source file (.wing)", index, globalLines, currentFunction, lines, file); } } else { - error("Syntax error", index, globalLines, currentFunction, lines); + error("Syntax error", index, globalLines, currentFunction, lines, file); } index++; globalLines++; if (_debug) console.log("-------------------"); } catch (e) { - error("Internal system error", index, globalLines, currentFunction, lines); + error("Internal system error", index, globalLines, currentFunction, lines, file); + index++; globalLines++; if (_debug) console.error(e); if (_debug) console.log("-------------------"); } @@ -2,27 +2,22 @@ -- This is a test program $test = 1 -function @hello - if $test == 1 do - @print hi - else do - @print no - end +function hello + print hi end -function @goodbye $thing +function goodbye $thing if defined $thing do - @print thing is defined: $thing + print thing is defined: $thing else do - @print thing is not defined + print thing is not defined end end -@hello -@goodbye hello world +hello +goodbye hello world -if $test == 1 do - @print this one doesn't exist: $thing -end +print hello $test, this one is also escaped: \$test -@print hello $test, this one is also escaped: \$test
\ No newline at end of file +#./demo.wing +#./test.wjs
\ No newline at end of file diff --git a/test.wjs b/test.wjs new file mode 100644 index 0000000..635625a --- /dev/null +++ b/test.wjs @@ -0,0 +1 @@ +console.log("Hello world!");
\ No newline at end of file |