Skip to content

Commit

Permalink
ES6: Use ES6 modules. Update node.
Browse files Browse the repository at this point in the history
  • Loading branch information
kanaka committed Sep 28, 2017
1 parent 130fdf5 commit a11a023
Show file tree
Hide file tree
Showing 23 changed files with 55 additions and 84 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ erlang/ebin
erlang/.rebar
erlang/src/*.beam
es6/mal.js
es6/build
es6/.esm-cache
factor/mal.factor
forth/mal.fs
fsharp/*.exe
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ elisp_STEP_TO_PROG = elisp/$($(1)).el
elixir_STEP_TO_PROG = elixir/lib/mix/tasks/$($(1)).ex
elm_STEP_TO_PROG = elm/$($(1)).js
erlang_STEP_TO_PROG = erlang/$($(1))
es6_STEP_TO_PROG = es6/build/$($(1)).js
es6_STEP_TO_PROG = es6/$($(1)).mjs
factor_STEP_TO_PROG = factor/$($(1))/$($(1)).factor
forth_STEP_TO_PROG = forth/$($(1)).fs
fsharp_STEP_TO_PROG = fsharp/$($(1)).exe
Expand Down
7 changes: 1 addition & 6 deletions es6/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,10 @@ WORKDIR /mal
RUN apt-get -y install g++

# Add nodesource apt repo config for 7.X
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash -
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -

# Install nodejs
RUN apt-get -y install nodejs

# Link common name
RUN ln -sf nodejs /usr/bin/node

ENV NPM_CONFIG_CACHE /mal/.npm

# ES6
RUN npm install -g babel-cli babel-plugin-transform-es2015-modules-commonjs
52 changes: 14 additions & 38 deletions es6/Makefile
Original file line number Diff line number Diff line change
@@ -1,56 +1,32 @@
export PATH := $(PATH):node_modules/.bin/

BABEL_OPTS = --source-maps true \
--plugins transform-es2015-modules-commonjs

SOURCES_BASE = node_readline.js types.js reader.js printer.js
SOURCES_LISP = env.js core.js stepA_mal.js
SOURCES_BASE = node_readline.js types.mjs reader.mjs printer.mjs
SOURCES_LISP = env.mjs core.mjs stepA_mal.mjs
SOURCES = $(SOURCES_BASE) $(SOURCES_LISP)

STEPS = step0_repl step1_read_print step2_eval step3_env \
step4_if_fn_do step5_tco step6_file step7_quote \
step8_macros step9_try stepA_mal
STEPS = step0_repl.mjs step1_read_print.mjs step2_eval.mjs step3_env.mjs \
step4_if_fn_do.mjs step5_tco.mjs step6_file.mjs \
step7_quote.mjs step8_macros.mjs step9_try.mjs stepA_mal.mjs

all: node_modules $(foreach s,$(STEPS),build/$(s).js)
all: node_modules

dist: mal.js mal

build/%.js: %.js node_modules
@mkdir -p $(dir $@)
babel $(BABEL_OPTS) $< --out-file $@
@echo >> $@ # workaround node-uglifier bug
node_modules:
npm install

$(STEPS): node_modules

mal.js: $(foreach s,$(SOURCES),build/$(s))
node -e 'nu = new (require("node-uglifier"))("./build/stepA_mal.js"); nu.merge().exportToFile("$@")'
mal.js: $(SOURCES)
cat $+ | sed 's/^export //' | grep -v "^import " >> $@

mal: mal.js
echo "#!/usr/bin/env node" > $@
cat $< >> $@
chmod +x $@

STEP0_DEPS = build/node_readline.js
STEP1_DEPS = $(STEP0_DEPS) build/types.js build/reader.js build/printer.js
STEP3_DEPS = $(STEP1_DEPS) build/env.js
STEP4_DEPS = $(STEP3_DEPS) build/core.js

build/step0_repl.js: $(STEP0_DEPS)
build/step1_read_print.js: $(STEP1_DEPS)
build/step2_eval.js: $(STEP1_DEPS)
build/step3_env.js: $(STEP3_DEPS)
build/step4_if_fn_do.js: $(STEP4_DEPS)
build/step5_tco.js: $(STEP4_DEPS)
build/step6_file.js: $(STEP4_DEPS)
build/step7_quote.js: $(STEP4_DEPS)
build/step8_macros.js: $(STEP4_DEPS)
build/step9_try.js: $(STEP4_DEPS)
build/stepA_mal.js: $(STEP4_DEPS)


node_modules:
npm install

clean:
rm -f build/* mal.js mal
rm -f mal.js mal
rm -rf node_modules

.PHONY: stats tests $(TESTS)

Expand Down
18 changes: 8 additions & 10 deletions es6/core.js → es6/core.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { _equal_Q, _clone, _keyword, _keyword_Q,
_list_Q, Vector, _assoc_BANG, _dissoc_BANG, Atom } from './types'
import { _equal_Q, _clone, _keyword, _keyword_Q } from './types'
import { _list_Q, Vector, _assoc_BANG, Atom } from './types'
import { pr_str } from './printer'
import { readline } from './node_readline'
import { read_str } from './reader'
Expand All @@ -22,16 +22,12 @@ function slurp(f) {
}

// Sequence functions
function conj(o, ...a) {
return _list_Q(o) ? a.reverse().concat(o) : Vector.from(o.concat(a))
}

function seq(obj) {
if (_list_Q(obj)) {
return obj.length > 0 ? obj : null
} else if (obj instanceof Vector) {
return obj.length > 0 ? Array.from(obj.slice(0)) : null
} else if (typeof obj === "string" && obj[0] !== '\u029e') {
} else if (typeof obj === "string" && !_keyword_Q(obj)) {
return obj.length > 0 ? obj.split('') : null
} else if (obj === null) {
return null
Expand All @@ -48,7 +44,7 @@ export const core_ns = new Map([
['nil?', a => a === null],
['true?', a => a === true],
['false?', a => a === false],
['string?', a => typeof a === "string" && a[0] !== '\u029e'],
['string?', a => typeof a === "string" && !_keyword_Q(a)],
['symbol', a => Symbol.for(a)],
['symbol?', a => typeof a === 'symbol'],
['keyword', _keyword],
Expand Down Expand Up @@ -79,7 +75,8 @@ export const core_ns = new Map([
['hash-map', (...a) => _assoc_BANG(new Map(), ...a)],
['map?', a => a instanceof Map],
['assoc', (m,...a) => _assoc_BANG(_clone(m), ...a)],
['dissoc', (m,...a) => _dissoc_BANG(_clone(m), ...a)],
['dissoc', (m,...a) => { let n = _clone(m); a.forEach(k => n.delete(k));
return n}],
['get', (m,a) => m === null ? null : m.has(a) ? m.get(a) : null],
['contains?', (m,a) => m.has(a)],
['keys', a => Array.from(a.keys())],
Expand All @@ -96,7 +93,8 @@ export const core_ns = new Map([
['apply', (f,...a) => f(...a.slice(0, -1).concat(a[a.length-1]))],
['map', (f,a) => Array.from(a.map(x => f(x)))],

['conj', conj],
['conj', (s,...a) => _list_Q(s) ? a.reverse().concat(s)
: Vector.from(s.concat(a))],
['seq', seq],

['meta', a => 'meta' in a ? a['meta'] : null],
Expand Down
File renamed without changes.
5 changes: 4 additions & 1 deletion es6/node_readline.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var rllib = ffi.Library(RL_LIB, {

var rl_history_loaded = false;

export function readline(prompt) {
function readline(prompt) {
prompt = prompt || "user> ";

if (!rl_history_loaded) {
Expand Down Expand Up @@ -41,3 +41,6 @@ export function readline(prompt) {

return line;
};

//exports.readline = readline
module.exports = {readline: readline}
9 changes: 4 additions & 5 deletions es6/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
"version": "0.0.1",
"description": "Make a Lisp (mal) language implemented in ES6 (ECMAScript 6 / ECMAScript 2015)",
"dependencies": {
"ffi": "2.0.x",
"node-uglifier": "0.4.3"
"@std/esm": "^0.11.0",
"ffi": "2.0.x"
},
"devDependencies": {
"babel-cli": "^6.0.0",
"babel-plugin-transform-es2015-modules-commonjs": "*"
"@std/esm": {
"cjs": true
}
}
4 changes: 2 additions & 2 deletions es6/printer.js → es6/printer.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { _symbol, _list_Q, Vector, Atom } from './types'
import { _list_Q, _keyword_Q, Vector, Atom } from './types'

export function pr_str(obj, print_readably) {
if (typeof print_readably === 'undefined') { print_readably = true }
Expand All @@ -14,7 +14,7 @@ export function pr_str(obj, print_readably) {
}
return "{" + ret.join(' ') + "}"
} else if (typeof obj === "string") {
if (obj[0] === '\u029e') {
if (_keyword_Q(obj)) {
return ':' + obj.slice(1)
} else if (_r) {
return '"' + obj.replace(/\\/g, "\\\\")
Expand Down
4 changes: 2 additions & 2 deletions es6/reader.js → es6/reader.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { _keyword, Vector, _assoc_BANG } from './types'
import { _keyword, _assoc_BANG, Vector } from './types';

export class BlankException extends Error {}

Expand Down Expand Up @@ -66,7 +66,7 @@ function read_list(reader, start, end) {

// read vector of tokens
function read_vector(reader) {
return Vector.from(read_list(reader, '[', ']'))
return Vector.from(read_list(reader, '[', ']'));
}

// read hash-map key/value pairs
Expand Down
2 changes: 1 addition & 1 deletion es6/run
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#!/bin/bash
exec node $(dirname $0)/build/${STEP:-stepA_mal}.js "${@}"
exec node -r @std/esm $(dirname $0)/${STEP:-stepA_mal}.mjs "${@}"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
34 changes: 17 additions & 17 deletions es6/types.js → es6/types.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@ export function _equal_Q (a, b) {

export function _clone(obj, new_meta) {
let new_obj = null
if (_list_Q(obj)) { new_obj = obj.slice(0) }
else if (obj instanceof Vector) { new_obj = Vector.from(obj.slice(0)) }
else if (obj instanceof Map) { new_obj = new Map(obj.entries()) }
else if (obj instanceof Function) { new_obj = obj.clone() }
else { throw Error("Invalid clone") }
if (new_meta !== undefined) { new_obj.meta = new_meta }
if (_list_Q(obj)) {
new_obj = obj.slice(0)
} else if (obj instanceof Vector) {
new_obj = Vector.from(obj)
} else if (obj instanceof Map) {
new_obj = new Map(obj.entries())
} else if (obj instanceof Function) {
let f = (...a) => obj.apply(f, a) // new function instance
new_obj = Object.assign(f, obj) // copy original properties
} else {
throw Error('Unsupported type for clone')
}
if (typeof new_meta !== 'undefined') { new_obj.meta = new_meta }
return new_obj
}

Expand All @@ -33,33 +40,26 @@ export function _malfunc(f, ast, env, params, meta=null, ismacro=false) {
return Object.assign(f, {ast, env, params, meta, ismacro})
}
export const _malfunc_Q = f => f.ast ? true : false
Function.prototype.clone = function() {
let f = (...a) => this.apply(f, a) // new function instance
return Object.assign(f, this) // copy original properties
}


// Keywords
export const _keyword = obj => _keyword_Q(obj) ? obj : '\u029e' + obj
export const _keyword_Q = obj => typeof obj === 'string' && obj[0] === '\u029e'

// Sequence collections
// Lists
export const _list_Q = obj => Array.isArray(obj) && !(obj instanceof Vector)

export class Vector extends Array {}
// Vectors
export class Vector extends Array { }

// Maps
export function _assoc_BANG(hm, ...args) {
if (args.length % 2 === 1) {
throw new Error('Odd number of assoc arguments')
}
// Use iterator/Array.from when it works
for (let i=0; i<args.length; i+=2) { hm.set(args[i], args[i+1]) }
return hm
}
export function _dissoc_BANG(hm, ...args) {
for (let i=0; i<args.length; i++) { hm.delete(args[i]) }
return hm
}


// Atoms
Expand Down

0 comments on commit a11a023

Please sign in to comment.