commit 4e46f693a896908f0f77fcbee216b7a8cf7a9cf8 Author: jusax23 Date: Fri Oct 14 19:30:47 2022 +0200 var, + diff --git a/js/ctx.js b/js/ctx.js new file mode 100644 index 0000000..e487a0e --- /dev/null +++ b/js/ctx.js @@ -0,0 +1,40 @@ +import { error } from "./lexer.js"; + +export class context{ + #list = {}; + constructor(){ + console.log("create"); + } + + add({name,size,amount=1,type = 0, content = 0}){ + console.log("add",name+""); + + this.#list[name+""] = {size,amount,type,content}; + console.log(this.#list); + } + find(name,pos){ + let elem = this.#list[name+""]; + console.log(this.#list); + if(!elem) error("Can not find '"+name+"' in context!"); + return elem; + } + build(){ + let out = ` + LOC Data_Segment + GREG @ + +`; + for(let Name in this.#list){ + let { size, amount, type, content } = this.#list[Name]; + if(size<=8&&amount==1){ + out += `${Name} ${(["BYTE", "WYDE", "TETRA", "TETRA", "OCTA", "OCTA", "OCTA", "OCTA"])[size-1]} ${content}\n`; + }else{ + out += ` +${name} BYTE ${content} + LOC ${name}+${size+amount+1}\n`; + } + } + out+=" LOC #100\nMain"; + return out; + } +} \ No newline at end of file diff --git a/js/execute.js b/js/execute.js new file mode 100644 index 0000000..9813954 --- /dev/null +++ b/js/execute.js @@ -0,0 +1,53 @@ +import { context } from "./ctx.js"; +import { createType, error } from "./lexer.js"; +import nativefunc from "./nativefunc.js"; +import { COMPUTE_TYPES } from "./types.js"; + +let nid = 0; + + +export function execute({ data, target = 0, ctx = new context()}){ + let [type, d] = createType(data); + if(type == "code"){ + try { + let { type, code } = nativefunc[data[0]]({ execute: ({data, target=0}) => execute({data, target,ctx}),data,target,nid:()=>nid++,ctx}); + return {code,type}; + } catch (e) { + console.log(e); + error(`'${data[0]}' is not a function`,...data.pos); + } + }else if (type == "var"){ + let { size, amount, type } = ctx.find(d+"V"); + if (size <= 8 && amount == 1){ + if(type == COMPUTE_TYPES.FLOAT){ + return { + type: 2, + code: ` ${size > 4 ? "LDOU" :"SFLOT"} $${target},${d}V` + } + }else{ + return { + type: type, + code: ` LD${(["B", "W", "T", "T", "O", "O", "O", "O"])[size-1]}${type==0?"U":""} $${target},${d}V` + } + } + }else{ + return { + type: 0, + code: ` LDA $${target},${elem.name}` + } + } + + }else if (type == "bool"){ + return { + code: ` SET $${target},${d}`, + type: COMPUTE_TYPES.UINT + } + }else if (type == "num"){ + + return { + code: ` SET $${target},${d}`, + type: COMPUTE_TYPES.UINT + } + } + throw new Error("nothing found"); +} \ No newline at end of file diff --git a/js/lexer.js b/js/lexer.js new file mode 100644 index 0000000..ff0ce20 --- /dev/null +++ b/js/lexer.js @@ -0,0 +1,180 @@ +export class LISPstring extends String { + #l; + #c; + constructor(string, line, char) { + super(string); + this.#l = line; + this.#c = char; + } + get lineCount() { + return this.#l; + } + get charCount() { + return this.#l; + } + get pos() { + return [this.#l, this.#c]; + } +} + +export class LISPcmd extends Array { + #l; + #c; + + constructor(code, line, char) { + var childs = cutCmd(code, line, char); + + super(...childs); + this.#l = line; + this.#c = char; + } + get lineCount() { + return this.#l; + } + get charCount() { + return this.#l; + } + get pos() { + return [this.#l, this.#c]; + } + get array(){ + return new Array(...this); + } +} + +export function error(msg, l = null, c = null) { + var out = "Error" + if (l != null && c != null) out += ` in line ${l} and character ${c}`; + out += ": " + msg; + console.log("\x1b[31m", out, "\x1b[0m"); + process.exit(1); +} + +var lispSeperator = [" ", ":", "\n"]; + +function cutCmd(code, line, chars) { + if (!code.startsWith("(")) return ["", error("Compiler Error", line, chars)]; + + if (!code.endsWith(")")) return ["", error("Compiler Error", line, chars)]; + + code = code.substring(1, code.length - 1); + + var countLinesBegin = line; + var countCharsBegin = chars; + + var countLines = line; + var countChars = chars; + var inC = 0; + var wasinC = false; + var inStr = 0; + var buffer = ""; + var i = 0; + var out = []; + + function finishBuff() { + out.push( + wasinC ? + new LISPcmd(buffer.trim(), countLinesBegin, countCharsBegin) + : + new LISPstring(buffer.trim(), countLinesBegin, countCharsBegin) + ); + countLinesBegin = countLines; + countCharsBegin = countChars; + buffer = ""; + wasinC = false; + } + + for (var i = 0; i < code.length; i++) { + + countChars++; + //console.log(code,countLines,countChars); + let c = code[i]; + if (!inC && !inStr) { + countLinesBegin = countLines; + countCharsBegin = countChars; + } + if (c == "\\") { + buffer += code[++i]; + continue; + } + if (inStr) { + if (c == "\n") { + countLines++; + countChars = 0; + } else if (c == '"') { + if (!inC) finishBuff(); + inStr = false; + } else { + buffer += c; + } + continue; + } + if (c == '"') { + inStr = true; + continue; + } + if (c == ";" && !inC) { + while (code[++i] != "\n") { } + countLines++; + countChars = 0; + continue; + } + if (c == "\n") { + countLines++; + countChars = 0; + } + if (/*(c == " "||c=="\n")*/lispSeperator.includes(c) && !inC) { + if (buffer.trim() != "") { + finishBuff(); + } + continue; + } + if (c == "(") { + if (!inC && buffer.trim() != "") { + finishBuff(); + } + inC++; + wasinC = true; + } + if (c == ")") { + inC--; + if (inC < 0) error("Closing braket to much!", countLines, countChars); + if (!inC) { + buffer += c; + finishBuff(); + continue; + } + } + buffer += c; + + } + if (inStr) error("Missing closing quotation mark!", countLines, countChars); + if (inC) error("Missing closing braket!", countLines, countChars); + + if (buffer.trim() != "") finishBuff(); + + return out; +} + + +export function createType(data) { + if (data == "true") { + return ["bool", 1]; + } + if (data == "false") { + return ["bool", 0]; + } + /*if (data == "NaN") { + return ["num", NaN]; + }*/ + /*if(typeof data == "string"&&data.startsWith('"') && data.endsWith('"')){ + return ["str", data.slice(1,-1)]; + }*/ + if ((data instanceof LISPstring) && !isNaN(data)) { + return ["num", Number(data)]; + } + if (data instanceof LISPcmd) { + return ["code", data]; + } + return ["var", data]; +} \ No newline at end of file diff --git a/js/nativefunc.js b/js/nativefunc.js new file mode 100644 index 0000000..77ec4d4 --- /dev/null +++ b/js/nativefunc.js @@ -0,0 +1,37 @@ +import { createType, error, LISPcmd } from "./lexer.js"; +import { convertType, getOutType } from "./types.js" + +export default { + "+": ({execute, data, target, nid, ctx}) => { + let params = data.array.slice(1).map((d, i) => execute({data:d, target:target + (i ? 0 : 1)})); + let outType = getOutType(...params.map(d => d.type)); + return { + type: outType, + code: params.map((d, i) => { + if (i == 0) return [ + d.code, + convertType(d.type, outType, target) + ]; + return [ + d.code, + convertType(d.type, outType, target + 1), + ` ${(["ADDU","ADD","FADD"])[outType]} $${target},$${target},$${target+1}` + ]; + }).flat(Infinity).join("\n") + } + }, + defvar: ({ execute, data, target, nid, ctx })=>{ + let param = data[3]; + let [type,d] = createType(param); + if(type == "var" || type == "code"){ + error("devfar with input is not implemented yet.",...param.pos) + }else{ + + ctx.add({ name: data[1]+"V", size: (Number(data[2].substring(1)) ?? 64) / 8, amount: 1, type: (((["u","i","f"]).indexOf(data[2].substring(0,1))+1)||1)-1,content:param }); + return { + code:"", + type:0 + } + } + } +} diff --git a/js/types.js b/js/types.js new file mode 100644 index 0000000..da74667 --- /dev/null +++ b/js/types.js @@ -0,0 +1,39 @@ +import { error } from "./lexer.js"; + +export const COMPUTE_TYPES = { + UINT: 0, + INT: 1, + FLOAT: 2 +} + +export const getOutType = (...types)=>Math.max(...types); + +export const convertType = (typein,typeout,reg) => { + if(typein == typeout) return "//no type conversion nessesary"; + if(typein == COMPUTE_TYPES.UINT && typeout == COMPUTE_TYPES.INT){ + return "//no type conversion nessesary (u -> i)"; + } + if(typein == COMPUTE_TYPES.INT && typeout == COMPUTE_TYPES.UINT){ + return `SET $${reg + 1},#7fffffffffffffff + AND $${reg},$${reg},$${reg + 1} convert i -> u`; + } + if(typein == COMPUTE_TYPES.INT && typeout == COMPUTE_TYPES.FLOAT){ + return ` FLOT $${reg},$${reg} convert i -> f`; + } + if(typein == COMPUTE_TYPES.UINT && typeout == COMPUTE_TYPES.FLOAT){ + return `SET $${reg + 1},#7fffffffffffffff + AND $${reg},$${reg},$${reg + 1} + FLOT $${reg},$${reg} convert i -> f`; + } + if(typein == COMPUTE_TYPES.FLOAT && typeout == COMPUTE_TYPES.INT){ + return ` FIX $${reg},$${reg} convert f -> i`; + } + if(typein == COMPUTE_TYPES.FLOAT && typeout == COMPUTE_TYPES.UINT){ + return ` FLOT $${reg},$${reg} convert i -> f + SET $${reg + 1},#7fffffffffffffff + AND $${reg},$${reg},$${reg+1}`; + } + console.log(typein,typeout) + error("[System error] Could not find a possible Type conversion.") +} + diff --git a/main.js b/main.js new file mode 100644 index 0000000..08357fc --- /dev/null +++ b/main.js @@ -0,0 +1,27 @@ +import * as fs from "fs"; +import { context } from "./js/ctx.js"; +import { execute } from "./js/execute.js"; +import { LISPcmd, LISPstring, createType } from "./js/lexer.js"; +var path = process.argv[2]; +var pathout = process.argv[3]; +if (!path || !pathout) { + console.log("PLease this Schema: node ToAs.js [path] [pathout]"); + process.exit(); +} +var file = fs.readFileSync(path).toString(); + +var data = new LISPcmd("(\n" + file + "\n)", 0, 0); + + +let code = ""; +var ctx = new context(); +for (var i = 0; i < data.length; i++) { + let { code: c, type } = execute({ data: data[i], ctx }); + code += c; +} + +let result = ctx.build(); +result+=code; +console.log(result); +fs.writeFileSync(pathout, result); +console.log(`Finished compiling in ${Math.round(performance.now()) / 1000}sec. Assembly saved to: ${pathout}`); diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..d6b9ba7 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "lisptommix", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + } + } +} diff --git a/node_modules/fs/README.md b/node_modules/fs/README.md new file mode 100644 index 0000000..5e9a74c --- /dev/null +++ b/node_modules/fs/README.md @@ -0,0 +1,9 @@ +# Security holding package + +This package name is not currently in use, but was formerly occupied +by another package. To avoid malicious use, npm is hanging on to the +package name, but loosely, and we'll probably give it to you if you +want it. + +You may adopt this package by contacting support@npmjs.com and +requesting the name. diff --git a/node_modules/fs/package.json b/node_modules/fs/package.json new file mode 100644 index 0000000..11661b0 --- /dev/null +++ b/node_modules/fs/package.json @@ -0,0 +1,20 @@ +{ + "name": "fs", + "version": "0.0.1-security", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/npm/security-holder.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/npm/security-holder/issues" + }, + "homepage": "https://github.com/npm/security-holder#readme" +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d990780 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "lisptommix", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "lisptommix", + "version": "0.0.1", + "license": "UNLICENSED", + "dependencies": { + "fs": "^0.0.1-security" + } + }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + } + }, + "dependencies": { + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..13d99d5 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "lisptommix", + "version": "0.0.1", + "description": "", + "main": "main.js", + "type":"module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git@jusax.de:jusax23/lispToMmix.git" + }, + "author": "jusax23", + "license": "UNLICENSED", + "dependencies": { + "fs": "^0.0.1-security" + } +} diff --git a/test.lisp b/test.lisp new file mode 100644 index 0000000..af30cc1 --- /dev/null +++ b/test.lisp @@ -0,0 +1,2 @@ +(defvar x:u16 5) +(+ 5 x) \ No newline at end of file diff --git a/test.mmo b/test.mmo new file mode 100644 index 0000000..40d5803 Binary files /dev/null and b/test.mmo differ diff --git a/test.mms b/test.mms new file mode 100644 index 0000000..658487e --- /dev/null +++ b/test.mms @@ -0,0 +1,11 @@ + + LOC Data_Segment + GREG @ + +xV WYDE 5 + LOC #100 +Main SET $1,5 +//no type conversion nessesary + LDWU $0,xV +//no type conversion nessesary + ADDU $0,$0,$1 \ No newline at end of file