modify readme

This commit is contained in:
Tan, Kian-ting 2024-04-03 22:47:44 +08:00
parent 3bb1609bbe
commit 56717bf77f
2 changed files with 94 additions and 12 deletions

View file

@ -26,6 +26,7 @@ var ItemType;
ItemType[ItemType["Str"] = 3] = "Str";
ItemType[ItemType["Bool"] = 4] = "Bool";
ItemType[ItemType["Clos"] = 5] = "Clos";
ItemType[ItemType["Ls"] = 6] = "Ls";
})(ItemType || (ItemType = {}));
const tokenizer = (0, typescript_parsec_1.buildLexer)([
[true, /^\d+/g, TokenKind.Int],
@ -150,6 +151,10 @@ function astToString(ast) {
let body = astToString(ast.body);
return `<closure; binding : ${binding}, body : ${body}>`;
}
else if (ast.type == ItemType.Ls) {
let body = astToString(ast.list);
return "'" + body;
}
else {
return ast.int.toString();
}
@ -221,6 +226,20 @@ function le(x, y) {
function ge(x, y) {
return x >= y;
}
/** list manipulation */
function car(x) {
let fst = x.list[0];
if (Array.isArray(fst)) {
let rtnList = {
type: ItemType.Ls,
list: fst,
};
return rtnList;
}
else {
return fst;
}
}
function extendEnv(env, vari, data) {
// add var
if (!(vari in env)) {
@ -248,10 +267,23 @@ function interp(prog, env) {
if (!Array.isArray(prog[0])) {
let op = prog[0];
if (op.type == ItemType.Id) {
if (op.id == "lambda") {
// a list
if (op.id == "quote") {
let body = prog[1];
if (!Array.isArray(body)) {
throw new Error("the argument of quote, aka: " + body + ", is not a list.");
}
else {
return {
type: ItemType.Ls,
list: body,
};
}
}
else if (op.id == "lambda") {
let vars = prog[1];
if (prog.length != 3) {
throw invalidLengthException('lambda', 3);
throw invalidLengthException('lambda', 2);
}
else if (!isItemArray(vars)) {
throw new Error("the vars of lambda should be a list of items");
@ -267,7 +299,7 @@ function interp(prog, env) {
else if (op.id == "let") {
let bindings = prog[1];
if (prog.length != 3) {
throw invalidLengthException('let', 3);
throw invalidLengthException('let', 2);
}
else if (!Array.isArray(bindings)) {
throw new Error("the bindings should be array");
@ -294,7 +326,7 @@ function interp(prog, env) {
}
else if (op.id == "if") {
if (prog.length != 4) {
throw invalidLengthException('if', 4);
throw invalidLengthException('if', 3);
}
else {
let cond = interp(prog[1], env);
@ -345,6 +377,18 @@ function interp(prog, env) {
}
else if (op.id == "==") {
return interpBinary(eq, argsMapped, true);
}
else if (op.id == "car") {
let arg = argsMapped[0];
if (prog.length != 2) {
throw invalidLengthException('car', 1);
}
else if (!arg.hasOwnProperty('type') || arg.type != ItemType.Ls) {
throw new Error("the arg of 'car' is not a list.");
}
else {
return car(arg);
}
// other named function call
}
else {
@ -364,7 +408,6 @@ function interp(prog, env) {
}
return interp(fuBody, newEnv);
}
throw new Error("aaaa");
}
}
// the caller should not be a non-id constant

View file

@ -42,9 +42,10 @@ enum ItemType {
Str,
Bool,
Clos,
Ls,
}
type Item = ItemStr | ItemInt | ItemId | ItemFlo | ItemBool | Closure;
type Item = ItemStr | ItemInt | ItemId | ItemFlo | ItemBool | Closure | List;
interface ItemStr {
type: ItemType.Str;
@ -70,6 +71,11 @@ interface ItemBool {
type: ItemType.Bool;
bool: boolean;
}
interface List {
type: ItemType.Ls;
list: AST[];
}
interface Env {
@ -256,6 +262,9 @@ function astToString(ast: AST): string {
let binding = astToString(ast.vars);
let body = astToString(ast.body);
return `<closure; binding : ${binding}, body : ${body}>`;
}else if (ast.type == ItemType.Ls){
let body = astToString(ast.list);
return "'"+body;
}
else {
return ast.int.toString();
@ -330,6 +339,20 @@ function ge(x: number, y: number): boolean {
return x >= y;
}
/** list manipulation */
function car(x : List) : Item {
let fst = (<AST[]>x.list)[0];
if (Array.isArray(fst)){
let rtnList : List = {
type: ItemType.Ls,
list: fst,
}
return rtnList;
}else{
return fst;
}
}
function extendEnv(env : Env, vari : string, data : AST) : Env{
// add var
if (!(vari in env)){
@ -361,12 +384,20 @@ function interp(prog: AST, env: Env): AST {
if (op.type == ItemType.Id) {
// a list
if (op.id == "quote"){
let body = prog[1];
if (!Array.isArray(body)){
throw new Error("the argument of quote, aka: "+body+", is not a list.");
}else{
return {
type: ItemType.Ls,
list: body,
}
if (op.id == "lambda"){
}
}
else if (op.id == "lambda"){
let vars = prog[1];
if (prog.length != 3){
throw invalidLengthException('lambda', 3);
throw invalidLengthException('lambda', 2);
}
else if (!isItemArray(vars)){
throw new Error("the vars of lambda should be a list of items");
@ -382,7 +413,7 @@ function interp(prog: AST, env: Env): AST {
else if (op.id == "let"){
let bindings = prog[1];
if (prog.length != 3){
throw invalidLengthException('let', 3);
throw invalidLengthException('let', 2);
}
else if (!Array.isArray(bindings)){
throw new Error("the bindings should be array");
@ -411,7 +442,7 @@ function interp(prog: AST, env: Env): AST {
}
else if(op.id == "if"){
if (prog.length != 4){
throw invalidLengthException('if', 4);
throw invalidLengthException('if', 3);
}else{
let cond = interp(prog[1], env);
if (Array.isArray(cond)){
@ -451,6 +482,15 @@ function interp(prog: AST, env: Env): AST {
return interpBinary(le, argsMapped,true);
} else if (op.id == "==") {
return interpBinary(eq, argsMapped,true);
} else if (op.id == "car") {
let arg = argsMapped[0];
if (prog.length != 2){
throw invalidLengthException('car', 1);
}else if (!arg.hasOwnProperty('type') || (<Item>arg).type != ItemType.Ls){
throw new Error("the arg of 'car' is not a list.")
}else{
return car((<List>arg));
}
// other named function call
} else {
let caller = interp(prog[0],env);
@ -471,7 +511,6 @@ function interp(prog: AST, env: Env): AST {
}
throw new Error("aaaa");
}}
// the caller should not be a non-id constant
} else {