var, +
This commit is contained in:
commit
4e46f693a8
14 changed files with 478 additions and 0 deletions
40
js/ctx.js
Normal file
40
js/ctx.js
Normal 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
53
js/execute.js
Normal 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
180
js/lexer.js
Normal 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
37
js/nativefunc.js
Normal 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
39
js/types.js
Normal 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
27
main.js
Normal 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
13
node_modules/.package-lock.json
generated
vendored
Normal 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
9
node_modules/fs/README.md
generated
vendored
Normal 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
20
node_modules/fs/package.json
generated
vendored
Normal 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
28
package-lock.json
generated
Normal 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
19
package.json
Normal 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
2
test.lisp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
(defvar x:u16 5)
|
||||||
|
(+ 5 x)
|
BIN
test.mmo
Normal file
BIN
test.mmo
Normal file
Binary file not shown.
11
test.mms
Normal file
11
test.mms
Normal 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
|
Loading…
Reference in a new issue