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