mirror of
https://github.com/kanaka/mal.git
synced 2024-11-10 02:45:44 +03:00
small fix
This commit is contained in:
parent
c527d56558
commit
677a1c9db1
@ -176,7 +176,7 @@ export const ns: Map<MalSymbol, MalFunction> = (() => {
|
||||
return new MalList(args);
|
||||
},
|
||||
"list?"(v: MalType): MalBoolean {
|
||||
return new MalBoolean(v instanceof MalList);
|
||||
return new MalBoolean(v.type === Node.List);
|
||||
},
|
||||
vector(...args: MalType[]): MalVector {
|
||||
return new MalVector(args);
|
||||
|
@ -4,7 +4,7 @@ import * as fs from "fs";
|
||||
|
||||
// IMPORTANT: choose one
|
||||
const RL_LIB = "libreadline"; // NOTE: libreadline is GPL
|
||||
//var RL_LIB = "libedit";
|
||||
// var RL_LIB = "libedit";
|
||||
|
||||
const HISTORY_FILE = path.join(process.env.HOME, ".mal-history");
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { readline } from "./node_readline";
|
||||
|
||||
import { Node, MalType, MalNumber, MalList, MalVector, MalHashMap, MalFunction } from "./types";
|
||||
import { Node, MalType, MalNumber, MalList, MalVector, MalHashMap, MalFunction, isSeq } from "./types";
|
||||
import { readStr } from "./reader";
|
||||
import { prStr } from "./printer";
|
||||
|
||||
@ -45,7 +45,10 @@ function evalMal(ast: MalType, env: MalEnvironment): MalType {
|
||||
if (ast.list.length === 0) {
|
||||
return ast;
|
||||
}
|
||||
const result = evalAST(ast, env) as MalList;
|
||||
const result = evalAST(ast, env);
|
||||
if (!isSeq(result)) {
|
||||
throw new Error(`unexpected return type: ${result.type}, expected: list or vector`);
|
||||
}
|
||||
const [f, ...args] = result.list;
|
||||
if (f.type !== Node.Function) {
|
||||
throw new Error(`unexpected token: ${f.type}, expected: function`);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { readline } from "./node_readline";
|
||||
|
||||
import { Node, MalType, MalNumber, MalList, MalVector, MalHashMap, MalSymbol, MalFunction } from "./types";
|
||||
import { Node, MalType, MalNumber, MalList, MalVector, MalHashMap, MalSymbol, MalFunction, isSeq } from "./types";
|
||||
import { Env } from "./env";
|
||||
import { readStr } from "./reader";
|
||||
import { prStr } from "./printer";
|
||||
@ -48,35 +48,41 @@ function evalMal(ast: MalType, env: Env): MalType {
|
||||
switch (first.v) {
|
||||
case "def!": {
|
||||
const [, key, value] = ast.list;
|
||||
if (key instanceof MalSymbol === false) {
|
||||
if (key.type !== Node.Symbol) {
|
||||
throw new Error(`unexpected toke type: ${key.type}, expected: symbol`);
|
||||
}
|
||||
if (!value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
return env.set(key as MalSymbol, evalMal(value, env))
|
||||
return env.set(key, evalMal(value, env));
|
||||
}
|
||||
case "let*": {
|
||||
let letEnv = new Env(env);
|
||||
const pairs = ast.list[1];
|
||||
if (pairs instanceof MalList === false && pairs instanceof MalVector === false) {
|
||||
if (!isSeq(pairs)) {
|
||||
throw new Error(`unexpected toke type: ${pairs.type}, expected: list or vector`);
|
||||
}
|
||||
const list = (pairs as (MalList | MalVector)).list;
|
||||
const list = pairs.list;
|
||||
for (let i = 0; i < list.length; i += 2) {
|
||||
const key = list[i];
|
||||
const value = list[i + 1];
|
||||
if (key.type !== Node.Symbol) {
|
||||
throw new Error(`unexpected token type: ${key.type}, expected: symbol`);
|
||||
}
|
||||
if (!key || !value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
|
||||
letEnv.set(key as MalSymbol, evalMal(value, letEnv));
|
||||
letEnv.set(key, evalMal(value, letEnv));
|
||||
}
|
||||
return evalMal(ast.list[2], letEnv);
|
||||
}
|
||||
}
|
||||
}
|
||||
const result = evalAST(ast, env) as MalList;
|
||||
const result = evalAST(ast, env);
|
||||
if (!isSeq(result)) {
|
||||
throw new Error(`unexpected return type: ${result.type}, expected: list or vector`);
|
||||
}
|
||||
const [f, ...args] = result.list;
|
||||
if (f.type !== Node.Function) {
|
||||
throw new Error(`unexpected token: ${f.type}, expected: function`);
|
||||
|
@ -55,7 +55,7 @@ function evalMal(ast: MalType, env: Env): MalType {
|
||||
if (!value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
return env.set(key, evalMal(value, env))
|
||||
return env.set(key, evalMal(value, env));
|
||||
}
|
||||
case "let*": {
|
||||
let letEnv = new Env(env);
|
||||
|
@ -56,7 +56,7 @@ function evalMal(ast: MalType, env: Env): MalType {
|
||||
if (!value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
return env.set(key, evalMal(value, env))
|
||||
return env.set(key, evalMal(value, env));
|
||||
}
|
||||
case "let*": {
|
||||
env = new Env(env);
|
||||
|
@ -56,7 +56,7 @@ function evalMal(ast: MalType, env: Env): MalType {
|
||||
if (!value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
return env.set(key, evalMal(value, env))
|
||||
return env.set(key, evalMal(value, env));
|
||||
}
|
||||
case "let*": {
|
||||
env = new Env(env);
|
||||
|
@ -96,7 +96,7 @@ function evalMal(ast: MalType, env: Env): MalType {
|
||||
if (!value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
return env.set(key, evalMal(value, env))
|
||||
return env.set(key, evalMal(value, env));
|
||||
}
|
||||
case "let*": {
|
||||
env = new Env(env);
|
||||
|
@ -142,7 +142,7 @@ function evalMal(ast: MalType, env: Env): MalType {
|
||||
if (!value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
return env.set(key, evalMal(value, env))
|
||||
return env.set(key, evalMal(value, env));
|
||||
}
|
||||
case "let*": {
|
||||
env = new Env(env);
|
||||
@ -273,7 +273,7 @@ replEnv.set(MalSymbol.get("*ARGV*"), new MalList([]));
|
||||
rep("(def! not (fn* (a) (if a false true)))");
|
||||
rep(`(def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) ")")))))`);
|
||||
rep(`(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw "odd number of forms to cond")) (cons 'cond (rest (rest xs)))))))`);
|
||||
rep('(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))');
|
||||
rep("(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))");
|
||||
|
||||
if (typeof process !== "undefined" && 2 < process.argv.length) {
|
||||
replEnv.set(MalSymbol.get("*ARGV*"), new MalList(process.argv.slice(3).map(s => new MalString(s))));
|
||||
|
@ -142,7 +142,7 @@ function evalMal(ast: MalType, env: Env): MalType {
|
||||
if (!value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
return env.set(key, evalMal(value, env))
|
||||
return env.set(key, evalMal(value, env));
|
||||
}
|
||||
case "let*": {
|
||||
env = new Env(env);
|
||||
@ -295,7 +295,7 @@ replEnv.set(MalSymbol.get("*ARGV*"), new MalList([]));
|
||||
rep("(def! not (fn* (a) (if a false true)))");
|
||||
rep(`(def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) ")")))))`);
|
||||
rep(`(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw "odd number of forms to cond")) (cons 'cond (rest (rest xs)))))))`);
|
||||
rep('(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))');
|
||||
rep("(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))");
|
||||
|
||||
if (typeof process !== "undefined" && 2 < process.argv.length) {
|
||||
replEnv.set(MalSymbol.get("*ARGV*"), new MalList(process.argv.slice(3).map(s => new MalString(s))));
|
||||
|
@ -142,7 +142,7 @@ function evalMal(ast: MalType, env: Env): MalType {
|
||||
if (!value) {
|
||||
throw new Error(`unexpected syntax`);
|
||||
}
|
||||
return env.set(key, evalMal(value, env))
|
||||
return env.set(key, evalMal(value, env));
|
||||
}
|
||||
case "let*": {
|
||||
env = new Env(env);
|
||||
|
Loading…
Reference in New Issue
Block a user