ctx steps, better errors, vars, chars, comp, if, math,

This commit is contained in:
jusax23 2022-10-15 23:25:07 +02:00
parent 77e6b3da48
commit 675a3d552a
13 changed files with 430 additions and 106 deletions

View file

@ -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;
}
}

9
js/errors.js Normal file
View file

@ -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);
}

View file

@ -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");
}

View file

@ -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)];
}

View file

@ -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,
};

116
js/nativefuncs/bool.js Normal file
View file

@ -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`
}
},
};

33
js/nativefuncs/lanes.js Normal file
View file

@ -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
`
}
},
};

81
js/nativefuncs/math.js Normal file
View file

@ -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")
}
},
}

40
js/nativefuncs/sys.js Normal file
View file

@ -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
}
},
};

56
js/nativefuncs/vars.js Normal file
View file

@ -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
};
},
}

View file

@ -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.")
}

View file

@ -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}`);

View file

@ -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",