This commit is contained in:
jusax23 2022-10-14 19:30:47 +02:00
commit 4e46f693a8
14 changed files with 478 additions and 0 deletions

40
js/ctx.js Normal file
View file

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

53
js/execute.js Normal file
View file

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

180
js/lexer.js Normal file
View file

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

37
js/nativefunc.js Normal file
View file

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

39
js/types.js Normal file
View file

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

27
main.js Normal file
View file

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

13
node_modules/.package-lock.json generated vendored Normal file
View file

@ -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=="
}
}
}

9
node_modules/fs/README.md generated vendored Normal file
View file

@ -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.

20
node_modules/fs/package.json generated vendored Normal file
View file

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

28
package-lock.json generated Normal file
View file

@ -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=="
}
}
}

19
package.json Normal file
View file

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

2
test.lisp Normal file
View file

@ -0,0 +1,2 @@
(defvar x:u16 5)
(+ 5 x)

BIN
test.mmo Normal file

Binary file not shown.

11
test.mms Normal file
View file

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