From 675a3d552ae725120c6418628004006343de1122 Mon Sep 17 00:00:00 2001 From: jusax23 Date: Sat, 15 Oct 2022 23:25:07 +0200 Subject: [PATCH] ctx steps, better errors, vars, chars, comp, if, math, --- js/ctx.js | 84 ++++++++++++++++++++--------- js/errors.js | 9 ++++ js/execute.js | 24 ++++++--- js/lexer.js | 6 ++- js/nativefunc.js | 79 ++++----------------------- js/nativefuncs/bool.js | 116 ++++++++++++++++++++++++++++++++++++++++ js/nativefuncs/lanes.js | 33 ++++++++++++ js/nativefuncs/math.js | 81 ++++++++++++++++++++++++++++ js/nativefuncs/sys.js | 40 ++++++++++++++ js/nativefuncs/vars.js | 56 +++++++++++++++++++ js/types.js | 1 - main.js | 4 +- package.json | 3 +- 13 files changed, 430 insertions(+), 106 deletions(-) create mode 100644 js/errors.js create mode 100644 js/nativefuncs/bool.js create mode 100644 js/nativefuncs/lanes.js create mode 100644 js/nativefuncs/math.js create mode 100644 js/nativefuncs/sys.js create mode 100644 js/nativefuncs/vars.js diff --git a/js/ctx.js b/js/ctx.js index b9b5d8f..8cb9a72 100644 --- a/js/ctx.js +++ b/js/ctx.js @@ -1,6 +1,8 @@ import { link } from "fs"; import { error } from "./lexer.js"; +let count = 0; + export class context{ #list = {}; #types = { @@ -18,30 +20,55 @@ export class context{ bool: {link:"u8"}, b: {link:"bool"}, }; - constructor(){ - console.log("create"); + #upper = []; + constructor(upper =[]){ + this.#upper = upper; } - - add({name,size,amount=1,type = 0, content = 0}){ - console.log("add",name+""); - - this.#list[name+""] = {size,amount,type,content}; - console.log(this.#list); + nextLevel(){ + return new context(this); + } + add({name,vType,size,amount=1,type = 0, content = 0,config = [1]}){ + if (!this.#list[vType]) this.#list[vType] = {}; + this.#list[vType][name+""] = {name: vType+(count++),size,amount,type,content,config}; } - find(name,pos){ - let elem = this.#list[name+""]; - console.log(this.#list); - if(!elem) error("Can not find '"+name+"' in context!"); + find(name, vType,pos=name.pos,quit=true){ + let elem = (this.#list[vType]??{})[name+""]??null; + + if(!elem){ + elem = this.#upper.find(name,vType,pos,false); + } + if(!elem&&quit) error("Can not find '"+name+"' in context!",...pos); return elem; } - getType(name){ - let type; - do{ + getType(name,pos=name.pos, quit = true){ + let lastName = name; + let type = this.#types[name]; + + if(!type){ + type = this.#upper.getType(name, pos, false); + if (!type) error("Can not find '" + name + "' in context", ...pos); + return type; + }else{ + if(type.link){ + type = this.getType(type.link,pos,false); + if (!type) error("Can not find '" + name + "' in context", ...pos); + return type; + }else{ + return type; + } + } + + /*do{ + if (type) type = this.#types[type.link] else type = this.#types[name]; - }while(type.link); - return type; + }while(type&&type.link);*/ + + + } + addLinkType(name,link){ + this.#types[name] = {link}; } build(){ @@ -50,17 +77,22 @@ export class context{ 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`; + + for(let vType in this.#list){ + for(let UName in this.#list[vType]){ + let { size, amount, type, content, name } = this.#list[vType][UName]; + if (!isNaN(content)) content = Number(content); + 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"; + out +=" LOC #100\nMain SWYM\n"; return out; } } \ No newline at end of file diff --git a/js/errors.js b/js/errors.js new file mode 100644 index 0000000..53409bb --- /dev/null +++ b/js/errors.js @@ -0,0 +1,9 @@ +import { error } from "./lexer.js" + + +export const argsCount = (name,num,pos)=>{ + error(`The native function '${name}' needs at least ${num} Arguments!`, ...pos); +} +export const argCount = (name,num,pos)=>{ + error(`The native function '${name}' needs ${num} Arguments!`, ...pos); +} diff --git a/js/execute.js b/js/execute.js index 9813954..f4e1680 100644 --- a/js/execute.js +++ b/js/execute.js @@ -7,33 +7,40 @@ let nid = 0; export function execute({ data, target = 0, ctx = new context()}){ + if(target > 255) error("To much registers are required to run this. Support for this case will be build in later!",...data.pos); 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}); + let { type, code } = nativefunc[data[0]]({ + execute: ({ data, target = 0, ctx:contx = ctx }) => execute({ data, target, ctx:contx }), + 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"); + let { size, amount, type, name } = ctx.find(d,"V",data.pos); if (size <= 8 && amount == 1){ if(type == COMPUTE_TYPES.FLOAT){ return { type: 2, - code: ` ${size > 4 ? "LDOU" :"SFLOT"} $${target},${d}V` + code: ` ${size > 4 ? "LDOU" :"LDSF"} $${target},${name}` } }else{ return { type: type, - code: ` LD${(["B", "W", "T", "T", "O", "O", "O", "O"])[size-1]}${type==0?"U":""} $${target},${d}V` + code: ` LD${(["B", "W", "T", "T", "O", "O", "O", "O"])[size-1]}${type==0?"U":""} $${target},${name}` } } }else{ return { type: 0, - code: ` LDA $${target},${elem.name}` + code: ` LDA $${target},${name}` } } @@ -43,11 +50,16 @@ export function execute({ data, target = 0, ctx = new context()}){ type: COMPUTE_TYPES.UINT } }else if (type == "num"){ - return { code: ` SET $${target},${d}`, type: COMPUTE_TYPES.UINT } + }else if (type == "str"){ + + 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 index ff0ce20..083f504 100644 --- a/js/lexer.js +++ b/js/lexer.js @@ -102,6 +102,7 @@ function cutCmd(code, line, chars) { countLines++; countChars = 0; } else if (c == '"') { + buffer += c; if (!inC) finishBuff(); inStr = false; } else { @@ -111,6 +112,7 @@ function cutCmd(code, line, chars) { } if (c == '"') { inStr = true; + buffer += c; continue; } if (c == ";" && !inC) { @@ -167,9 +169,9 @@ export function createType(data) { /*if (data == "NaN") { return ["num", NaN]; }*/ - /*if(typeof data == "string"&&data.startsWith('"') && data.endsWith('"')){ + if ((data instanceof LISPstring)&&data.startsWith('"') && data.endsWith('"')){ return ["str", data.slice(1,-1)]; - }*/ + } if ((data instanceof LISPstring) && !isNaN(data)) { return ["num", Number(data)]; } diff --git a/js/nativefunc.js b/js/nativefunc.js index 05e657f..213efe3 100644 --- a/js/nativefunc.js +++ b/js/nativefunc.js @@ -1,70 +1,13 @@ -import { createType, error, LISPcmd } from "./lexer.js"; -import { convertType, getOutType } from "./types.js" +import bool from "./nativefuncs/bool.js"; +import lanes from "./nativefuncs/lanes.js"; +import math from "./nativefuncs/math.js"; +import sys from "./nativefuncs/sys.js"; +import vars from "./nativefuncs/vars.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") - } - }, - "-": ({ 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), - ` ${(["SUBU", "SUB", "FSUB"])[outType]} $${target},$${target},$${target + 1}` - ]; - }).flat(Infinity).join("\n") - } - }, - defvar: ({ execute, data, target, nid, ctx }) => { - let param = data[3]; - let [type, d] = createType(param); - - let varType = ctx.getType(data[2]); - if (varType.content) error("A variable only can be created with a primitive Type.", ...data[2].pos); - - if (type == "var" || type == "code") { - error("devfar with input is not implemented yet.", ...param.pos) - } else { - ctx.add({ name: data[1] + "V", size: varType.size, amount: 1, type: varType.type, content: param }); - return { - code: "", - type: 0 - } - } - }, - defarr: ({ execute, data, target, nid, ctx }) => { - let param = data.slice(3).map(d => Number(d)); - let varType = ctx.getType(data[2]); - let amount = param.reduce((v, c) => v * c, 1); - - ctx.add({ name: data[1] + "V", size: varType.size, amount: amount, type: varType.type, content: param }); - - return { - code: "", - type: 0 - }; - } -} + ...math, + ...vars, + ...lanes, + ...sys, + ...bool, +}; \ No newline at end of file diff --git a/js/nativefuncs/bool.js b/js/nativefuncs/bool.js new file mode 100644 index 0000000..9eba072 --- /dev/null +++ b/js/nativefuncs/bool.js @@ -0,0 +1,116 @@ +import { argCount } from "../errors.js"; +import { COMPUTE_TYPES, convertType, getOutType } from "../types.js"; + + +export default { + "<": ({ execute, data, target, nid, ctx }) => { + if (data.length != 3) argCount("<",2,data.pos); + let param1 = execute({ data: data[1], target}); + let param2 = execute({ data: data[2], target:target+1}); + let outType = getOutType(param1.type,param2.type); + return { + type: COMPUTE_TYPES.UINT, + code: `${param1.code} +${convertType(param1.type, outType, target) } +${param2.code} +${convertType(param2.type, outType, target+1)} + ${ (["CMPU", "CMP", "FCMP"])[outType] } $${ target },$${ target },$${ target + 1 } + ZSN $${target},$${target},1` + } + }, + "<=": ({ execute, data, target, nid, ctx }) => { + if (data.length != 3) argCount("<=",2,data.pos); + let param1 = execute({ data: data[1], target}); + let param2 = execute({ data: data[2], target:target+1}); + let outType = getOutType(param1.type,param2.type); + return { + type: COMPUTE_TYPES.UINT, + code: `${param1.code} +${convertType(param1.type, outType, target) } +${param2.code} +${convertType(param2.type, outType, target+1)} + ${ (["CMPU", "CMP", "FCMP"])[outType] } $${ target },$${ target },$${ target + 1 } + ZSNP $${target},$${target},1` + } + }, + "=": ({ execute, data, target, nid, ctx }) => { + if (data.length != 3) argCount("=",2,data.pos); + let param1 = execute({ data: data[1], target}); + let param2 = execute({ data: data[2], target:target+1}); + let outType = getOutType(param1.type,param2.type); + return { + type: COMPUTE_TYPES.UINT, + code: `${param1.code} +${convertType(param1.type, outType, target) } +${param2.code} +${convertType(param2.type, outType, target+1)} + ${ (["CMPU", "CMP", "FCMP"])[outType] } $${ target },$${ target },$${ target + 1 } + ZSZ $${target},$${target},1` + } + }, + ">=": ({ execute, data, target, nid, ctx }) => { + if (data.length != 3) argCount(">=",2,data.pos); + let param1 = execute({ data: data[1], target}); + let param2 = execute({ data: data[2], target:target+1}); + let outType = getOutType(param1.type,param2.type); + return { + type: COMPUTE_TYPES.UINT, + code: `${param1.code} +${convertType(param1.type, outType, target) } +${param2.code} +${convertType(param2.type, outType, target+1)} + ${ (["CMPU", "CMP", "FCMP"])[outType] } $${ target },$${ target },$${ target + 1 } + ZSNN $${target},$${target},1` + } + }, + ">": ({ execute, data, target, nid, ctx }) => { + if (data.length != 3) argCount(">",2,data.pos); + let param1 = execute({ data: data[1], target}); + let param2 = execute({ data: data[2], target:target+1}); + let outType = getOutType(param1.type,param2.type); + return { + type: COMPUTE_TYPES.UINT, + code: `${param1.code} +${convertType(param1.type, outType, target) } +${param2.code} +${convertType(param2.type, outType, target+1)} + ${ (["CMPU", "CMP", "FCMP"])[outType] } $${ target },$${ target },$${ target + 1 } + ZSP $${target},$${target},1` + } + }, + "!=": ({ execute, data, target, nid, ctx }) => { + if (data.length != 3) argCount("!=",2,data.pos); + let param1 = execute({ data: data[1], target}); + let param2 = execute({ data: data[2], target:target+1}); + let outType = getOutType(param1.type,param2.type); + return { + type: COMPUTE_TYPES.UINT, + code: `${param1.code} +${convertType(param1.type, outType, target) } +${param2.code} +${convertType(param2.type, outType, target+1)} + ${ (["CMPU", "CMP", "FCMP"])[outType] } $${ target },$${ target },$${ target + 1 } + ZSNZ $${target},$${target},1` + } + }, + "!": ({ execute, data, target, nid, ctx }) => { + if (data.length != 2) argCount("!", 1, data.pos); + let param = execute({ data: data[1], target }); + return { + type: COMPUTE_TYPES.UINT, + code: `${param.code} + ${(["CMPU", "CMP", "FCMP"])[param.type]} $${target},$${target},0 + ZSZ $${target},$${target},1` + } + }, + "!!": ({ execute, data, target, nid, ctx }) => { + if (data.length != 2) argCount("!!", 1, data.pos); + let param = execute({ data: data[1], target }); + return { + type: COMPUTE_TYPES.UINT, + code: `${param.code} + ${(["CMPU", "CMP", "FCMP"])[param.type]} $${target},$${target},0 + ZSNZ $${target},$${target},1` + } + }, +}; \ No newline at end of file diff --git a/js/nativefuncs/lanes.js b/js/nativefuncs/lanes.js new file mode 100644 index 0000000..4d18b03 --- /dev/null +++ b/js/nativefuncs/lanes.js @@ -0,0 +1,33 @@ +import { argsCount } from "../errors.js"; + + +export default { + progn: ({ execute, data, target, nid, ctx }) => { + if (data.length < 2) argsCount("progn", 1, data.pos); + let newctx = ctx.nextLevel(); + return { + type: 0, + code: `//new code Block +${data.array.slice(1).map(d => execute({ data: d, target, ctx: newctx })).join("\n")} +//end Code Block` + } + }, + if: ({ execute, data, target, nid, ctx }) => { + if (data.length < 3) argsCount("if", 2, data.pos); + let condition = execute({ data: data[1], target }); + let id1 = nid(); + let id2 = nid(); + return { + type: 0, + code: `//if + ${condition.code} + BZ $${target},else${id1} +${execute({ data: data[2] }).code} + ${data.length > 3 ? "JMP fi" + id2 : ""} +else${id1} SWYM +${data.length > 3 ? execute({ data: data[2] }).code : ""} +fi${id2} SWYM + ` + } + }, +}; \ No newline at end of file diff --git a/js/nativefuncs/math.js b/js/nativefuncs/math.js new file mode 100644 index 0000000..bc8bb0b --- /dev/null +++ b/js/nativefuncs/math.js @@ -0,0 +1,81 @@ +import { argsCount } from "../errors.js"; +import { convertType, getOutType } from "../types.js" + +export default { + "+": ({ execute, data, target, nid, ctx }) => { + if (data.length < 3) argsCount("+",2,data.pos); + 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") + } + }, + "-": ({ execute, data, target, nid, ctx }) => { + if (data.length < 3) argsCount("-", 2, data.pos); + 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), + ` ${(["SUBU", "SUB", "FSUB"])[outType]} $${target},$${target},$${target + 1}` + ]; + }).flat(Infinity).join("\n") + } + }, + "*": ({ execute, data, target, nid, ctx }) => { + if (data.length < 3) argsCount("*", 2, data.pos); + 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), + ` ${(["MULU", "MUL", "FMUL"])[outType]} $${target},$${target},$${target + 1}` + ]; + }).flat(Infinity).join("\n") + } + }, + "/": ({ execute, data, target, nid, ctx }) => { + if (data.length < 3) argsCount("/", 2, data.pos); + 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), + ` ${(["DIVU", "DIV", "FDIV"])[outType]} $${target},$${target},$${target + 1}` + ]; + }).flat(Infinity).join("\n") + } + }, +} \ No newline at end of file diff --git a/js/nativefuncs/sys.js b/js/nativefuncs/sys.js new file mode 100644 index 0000000..e557658 --- /dev/null +++ b/js/nativefuncs/sys.js @@ -0,0 +1,40 @@ + + +export default { + assm: ({ execute, data, target, nid, ctx }) => { + let cmds = data.array.slice(1, -1); + let type = data.array.slice(-1)[0]; + return { + code: "\n" + cmds.map(d => { + let out = d.slice(1, -1); + ([["?7", 7], ["?6", 6], ["?5", 5], ["?4", 4], ["?3", 3], ["?2", 2], ["?1", 1], ["?0", 0]]).map(a => { + out = out.split(a[0]).join("$" + (target + a[1])); + }); + return out; + }).join("\n") + "\n", + type + }; + }, + printRaw: ({ execute, data, target, nid, ctx }) => { + let { code, type } = execute({ data: data[1], target: target }); + return { + code: `${code} + SET $255,$${target} + TRAP 0,Fputs,StdOut`, + type + }; + }, + addr: ({ execute, data, target, nid, ctx }) => { + let nv = ctx.find(data[1], "V"); + return { + code: ` LDA $${target},${nv.name}`, + type: 0 + }; + }, + exit: () => { + return { + code: " TRAP 0,Halt,0", + type: 0 + } + }, +}; \ No newline at end of file diff --git a/js/nativefuncs/vars.js b/js/nativefuncs/vars.js new file mode 100644 index 0000000..6d00973 --- /dev/null +++ b/js/nativefuncs/vars.js @@ -0,0 +1,56 @@ +import { createType, error, LISPcmd } from "../lexer.js"; +import { COMPUTE_TYPES, convertType } from "../types.js"; + +export default { + defvar: ({ execute, data, target, nid, ctx }) => { + let param = data[3]; + let [type, d] = createType(param); + + let varType = ctx.getType(data[2]); + if (varType.content) error("A variable only can be created with a primitive Type.", ...data[2].pos); + + if (type == "var" || type == "code") { + error("devfar with input is not implemented yet.", ...param.pos) + } else { + ctx.add({ name: data[1], vType: "V", size: varType.size, amount: 1, type: varType.type, content: param }); + return { + code: "", + type: 0 + } + } + }, + set: ({ execute, data, target, nid, ctx }) => { + let toSet = ctx.find(data[1],"V"); + let { code, type } = execute({ data: data[2], target }); + if(toSet.type == COMPUTE_TYPES.FLOAT){ + return { + code: `${code} +${convertType(type, toSet.type, target)} + ${toSet.size > 4 ? "STOU" : "STSF"} $${target},${toSet.name}`, + type: toSet.type + }; + + }else{ + return { + code: `${code} +${convertType(type, toSet.type, target)} + ST${(["B", "W", "T", "T", "O", "O", "O", "O"])[toSet.size - 1]}${type == 0 ? "U" : ""} $${target},${toSet.name}`, + type: toSet.type + }; + } + + }, + defarr: ({ execute, data, target, nid, ctx }) => { + let param = data.array.slice(3, -1).map(d => Number(d)); + + let varType = ctx.getType(data[2]); + let amount = param.reduce((v, c) => v * c, 1); + + ctx.add({ name: data[1], vType:"V", size: varType.size, amount: amount, type: varType.type, config: param, content: data.array.slice(-1)[0] }); + + return { + code: "", + type: 0 + }; + }, +} \ No newline at end of file diff --git a/js/types.js b/js/types.js index da74667..16e9b18 100644 --- a/js/types.js +++ b/js/types.js @@ -33,7 +33,6 @@ export const convertType = (typein,typeout,reg) => { 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 index 08357fc..9d68961 100644 --- a/main.js +++ b/main.js @@ -17,11 +17,11 @@ 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; + if(c=="")continue; + code += c+"\n"; } 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/package.json b/package.json index 13d99d5..11acec4 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "main.js", "type":"module", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "run": "node . test.lisp test.mms && mmixal test.mms && mmix test.mmo" }, "repository": { "type": "git",