1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-10 02:45:44 +03:00

small fix

This commit is contained in:
vvakame 2017-02-25 14:44:11 +09:00
parent c527d56558
commit 677a1c9db1
11 changed files with 29 additions and 20 deletions

View File

@ -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);

View File

@ -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");

View File

@ -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`);

View File

@ -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`);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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))));

View File

@ -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))));

View File

@ -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);