Multiple implementations (JS, Wasm, C) of a Lisp.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

96 lines
2.9 KiB

import { DataTypes } from './datatypes.js';
import { Env } from './env.js';
export class Printer {
static princToString(sexp) {
if (sexp.type === DataTypes.Cons) {
if (sexp.car.type === DataTypes.Symbol &&
['QUOTE', 'QUASIQUOTE', 'UNQUOTE', 'UNQUOTE-SPLICING'].includes(sexp.car.value)) {
let prefix = '';
switch (sexp.car.value) {
case 'QUOTE': prefix = '\''; break;
case 'QUASIQUOTE': prefix = '`'; break;
case 'UNQUOTE': prefix = ','; break;
case 'UNQUOTE-SPLICING': prefix = ',@'; break;
}
return prefix + Printer.princToString(sexp.cdr.car);
} else {
let result = Printer.princToString(sexp.car);
if (sexp.cdr.type !== DataTypes.Nil && sexp.cdr.type === DataTypes.Cons) {
let s = Printer.princToString(sexp.cdr);
result += ' ' + s.substr(1, s.length - 2);
} else if (sexp.cdr.type !== DataTypes.Nil) {
result += ' . ' + Printer.princToString(sexp.cdr);
}
return '(' + result.trim() + ')';
}
}
switch(sexp.type) {
case DataTypes.String:
// return `"${sexp.value}"`;
return `${sexp.value}`;
case DataTypes.Symbol:
return sexp.value.toUpperCase();
case DataTypes.Number:
return `${sexp.value}`;
case DataTypes.Function:
return `<FUNCTION ${sexp.value}>`;
case DataTypes.True:
return 'T';
case DataTypes.Nil:
return 'NIL';
}
}
static prin1ToString(sexp) {
if (sexp.type === DataTypes.Cons) {
if (sexp.car.type === DataTypes.Symbol &&
['QUOTE', 'QUASIQUOTE', 'UNQUOTE', 'UNQUOTE-SPLICING'].includes(sexp.car.value)) {
let prefix = '';
switch (sexp.car.value) {
case 'QUOTE': prefix = '\''; break;
case 'QUASIQUOTE': prefix = '`'; break;
case 'UNQUOTE': prefix = ','; break;
case 'UNQUOTE-SPLICING': prefix = ',@'; break;
}
return prefix + Printer.princToString(sexp.cdr.car);
} else {
let result = Printer.princToString(sexp.car);
if (sexp.cdr.type !== DataTypes.Nil && sexp.cdr.type === DataTypes.Cons) {
let s = Printer.princToString(sexp.cdr);
result += ' ' + s.substr(1, s.length - 2);
} else if (sexp.cdr.type !== DataTypes.Nil) {
result += ' . ' + Printer.princToString(sexp.cdr);
}
return '(' + result.trim() + ')';
}
}
switch(sexp.type) {
case DataTypes.String:
return `"${sexp.value}"`;
case DataTypes.Symbol:
return sexp.value.toUpperCase();
case DataTypes.Number:
return `${sexp.value}`;
case DataTypes.Function:
return `<FUNCTION ${sexp.value}>`;
case DataTypes.True:
return 'T';
case DataTypes.Nil:
return 'NIL';
}
}
static princ(sexp, env) {
Env.get(env, 'STANDARD-OUTPUT-STREAM').pushData(Printer.princToString(sexp)/*.trim()*/);
}
static print(sexp, env) {
Env.get(env, 'STANDARD-OUTPUT-STREAM').pushData('\n');
Printer.princ(sexp, env);
}
static prin1(sexp, env) {
Env.get(env, 'STANDARD-OUTPUT-STREAM').pushData(Printer.prin1ToString(sexp)/*.trim()*/);
}
}