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 ``; 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 ``; 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()*/); } }