From 56717bf77f1bbcd885839c668a426efd57d6a5a2 Mon Sep 17 00:00:00 2001 From: Tan Kian-ting Date: Wed, 3 Apr 2024 22:47:44 +0800 Subject: [PATCH] modify readme --- src/index.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++----- src/index.ts | 53 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 94 insertions(+), 12 deletions(-) diff --git a/src/index.js b/src/index.js index 54916db..466b653 100644 --- a/src/index.js +++ b/src/index.js @@ -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 ``; } + 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 diff --git a/src/index.ts b/src/index.ts index d8304e6..f343703 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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 ``; + }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 = (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') || (arg).type != ItemType.Ls){ + throw new Error("the arg of 'car' is not a list.") + }else{ + return car((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 { -- 2.39.2