modify readme
This commit is contained in:
parent
3bb1609bbe
commit
56717bf77f
2 changed files with 94 additions and 12 deletions
53
src/index.js
53
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 `<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
|
||||
|
|
53
src/index.ts
53
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 `<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 {
|
||||
|
|
Loading…
Reference in a new issue