1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 01:57:09 +03:00

Haxe: step0 and step1.

This commit is contained in:
Joel Martin 2016-01-08 21:18:41 -06:00
parent b1fef5d72a
commit 6c4c14bd8a
9 changed files with 297 additions and 3 deletions

View File

@ -22,9 +22,10 @@ mal_TEST_OPTS = --start-timeout 60 --test-timeout 120
# Settings
#
IMPLS = awk bash c d clojure coffee cpp crystal cs erlang elixir es6 factor forth fsharp go groovy \
guile haskell java julia js kotlin lua make mal ocaml matlab miniMAL nim \
perl php ps python r racket rpython ruby rust scala swift tcl vb vimscript
IMPLS = awk bash c d clojure coffee cpp crystal cs erlang elixir es6 \
factor forth fsharp go groovy guile haskell haxe java julia \
js kotlin lua make mal ocaml matlab miniMAL nim perl php ps \
python r racket rpython ruby rust scala swift tcl vb vimscript
step0 = step0_repl
step1 = step1_read_print
@ -112,6 +113,7 @@ go_STEP_TO_PROG = go/$($(1))
groovy_STEP_TO_PROG = groovy/$($(1)).groovy
java_STEP_TO_PROG = java/src/main/java/mal/$($(1)).java
haskell_STEP_TO_PROG = haskell/$($(1))
haxe_STEP_TO_PROG = haxe/$($(1)).py
julia_STEP_TO_PROG = julia/$($(1)).jl
js_STEP_TO_PROG = js/$($(1)).js
kotlin_STEP_TO_PROG = kotlin/$($(1)).jar
@ -167,6 +169,7 @@ fsharp_RUNSTEP = mono ../$(2) --raw $(3)
go_RUNSTEP = ../$(2) $(3)
groovy_RUNSTEP = groovy ../$(2) $(3)
haskell_RUNSTEP = ../$(2) $(3)
haxe_RUNSTEP = python3 ../$(2) $(3)
java_RUNSTEP = mvn -quiet exec:java -Dexec.mainClass="mal.$($(1))" $(if $(3), -Dexec.args="$(3)",)
julia_RUNSTEP = ../$(2) $(3)
js_RUNSTEP = node ../$(2) $(3)

33
haxe/Dockerfile Normal file
View File

@ -0,0 +1,33 @@
FROM ubuntu:vivid
MAINTAINER Joel Martin <github@martintribe.org>
##########################################################
# General requirements for testing or common across many
# implementations
##########################################################
RUN apt-get -y update
# Required for running tests
RUN apt-get -y install make python
# Some typical implementation and test requirements
RUN apt-get -y install curl libreadline-dev libedit-dev
RUN mkdir -p /mal
WORKDIR /mal
##########################################################
# Specific implementation requirements
##########################################################
# Install Haxe
RUN apt-get -y install software-properties-common && \
add-apt-repository -y ppa:haxe/releases && \
apt-get -y update
RUN apt-get install -y haxe && \
mkdir /root/haxelib && haxelib setup /root/haxelib
# Install support for C++ compilation
RUN apt-get -y install g++
RUN haxelib install hxcpp

8
haxe/Makefile Normal file
View File

@ -0,0 +1,8 @@
# Python step rules
s%.py: S%.hx
haxe -main $(patsubst %.hx,%,$<) -python $@
step1_read_print.py: types/Types.hx reader/Reader.hx printer/Printer.hx
clean:
rm -r *.py

38
haxe/Step0_repl.hx Normal file
View File

@ -0,0 +1,38 @@
class Step0_repl {
// READ
static function READ(str:String) {
return str;
}
// EVAL
static function EVAL(ast:String, env:String) {
return ast;
}
// PRINT
static function PRINT(exp:String) {
return exp;
}
// repl
static function rep(line:String) {
return PRINT(EVAL(READ(line), ""));
}
public static function main() {
#if js
#error "JS not supported yet"
#end
while (true) {
try {
Sys.print("user> ");
var line = Sys.stdin().readLine();
Sys.println(rep(line));
} catch (exc:haxe.io.Eof) {
Sys.exit(0);
} catch (exc:Dynamic) {
Sys.println(exc);
}
}
}
}

45
haxe/Step1_read_print.hx Normal file
View File

@ -0,0 +1,45 @@
import types.Types.MalType;
import reader.*;
import printer.*;
class Step1_read_print {
// READ
static function READ(str:String):MalType {
return Reader.read_str(str);
}
// EVAL
static function EVAL(ast:MalType, env:String) {
return ast;
}
// PRINT
static function PRINT(exp:MalType):String {
return Printer.pr_str(exp, true);
}
// repl
static function rep(line:String) {
return PRINT(EVAL(READ(line), ""));
}
public static function main() {
#if js
#error "JS not supported yet"
#end
while (true) {
try {
Sys.print("user> ");
var line = Sys.stdin().readLine();
if (line == "") { continue; }
Sys.println(rep(line));
} catch (exc:BlankLine) {
continue;
} catch (exc:haxe.io.Eof) {
Sys.exit(0);
} catch (exc:Dynamic) {
Sys.println(exc);
}
}
}
}

30
haxe/printer/Printer.hx Normal file
View File

@ -0,0 +1,30 @@
package printer;
import types.Types.MalType;
import types.Types.MalType.*;
class Printer {
public static function pr_str(exp:MalType, print_readably:Bool = true) {
var _r = print_readably;
return switch(exp) {
case MalNil: "nil";
case MalTrue: "true";
case MalFalse: "false";
case MalInt(v): Std.string(v);
case MalString(v):
if (_r) {
'"' + v + '"';
} else {
v;
}
case MalSymbol(v): Std.string(v);
case MalList(l):
var lst = l.map(function(e) {return pr_str(e,_r);});
"(" + lst.join(" ") + ")";
case MalVector(l):
var lst = l.map(function(e) {return pr_str(e,_r);});
"[" + lst.join(" ") + "]";
case _: throw "unknown type for printing";
}
}
}

6
haxe/reader/BlankLine.hx Normal file
View File

@ -0,0 +1,6 @@
package reader;
class BlankLine {
public function new() {
}
}

112
haxe/reader/Reader.hx Normal file
View File

@ -0,0 +1,112 @@
package reader;
import types.Types.MalType;
import types.Types.MalType.*;
class Reader {
// Reader class implementation
var tokens:Array<String>;
var position:Int = 0;
public function new(toks:Array<String>) {
tokens = toks;
}
public function next() {
return tokens[position++];
}
public function peek() {
if (tokens.length > position) {
return tokens[position];
} else {
return null;
}
}
// Static functions grouped with Reader class
static function tokenize(str:String) {
var re = ~/[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)/g;
var tokens = new Array<String>();
var pos = 0;
while (re.matchSub(str, pos)) {
var t = re.matched(1);
if (t == "" || t.charAt(0) == ";") { break; }
tokens.push(t);
var pos_len = re.matchedPos();
pos = pos_len.pos + pos_len.len;
}
return tokens;
}
static function read_atom(rdr:Reader) {
var re_int = ~/^[0-9]*$/;
var re_str = ~/^".*"$/;
var token = rdr.next();
return switch (token) {
case "nil":
MalNil;
case "true":
MalTrue;
case "false":
MalFalse;
case _ if (re_int.match(token)):
MalInt(Std.parseInt(token));
case _ if (re_str.match(token)):
MalString(token.substr(1, token.length-2));
case _:
MalSymbol(token);
}
}
static function read_seq(rdr:Reader, start, end) {
var lst = [];
var token = rdr.next();
if (token != start) {
throw "expected '$start'";
}
while ((token = rdr.peek()) != end) {
if (token == null) {
throw "expected '$end', got EOF";
}
lst.push(read_form(rdr));
}
rdr.next();
return lst;
}
static function read_form(rdr:Reader):MalType {
var token = rdr.peek();
return switch (token) {
// reader macros/transforms
case "'": rdr.next();
MalList([MalSymbol("quote"), read_form(rdr)]);
case "`": rdr.next();
MalList([MalSymbol("quasiquote"), read_form(rdr)]);
case "~": rdr.next();
MalList([MalSymbol("unquote"), read_form(rdr)]);
case "~@": rdr.next();
MalList([MalSymbol("splice-unquote"), read_form(rdr)]);
case "^": rdr.next();
var meta = read_form(rdr);
MalList([MalSymbol("with-meta"), read_form(rdr), meta]);
case "@": rdr.next();
MalList([MalSymbol("deref"), read_form(rdr)]);
// list
case ")": throw("unexpected ')'");
case "(": MalList(read_seq(rdr, '(', ')'));
case "]": throw("unexpected ']'");
case "[": MalVector(read_seq(rdr, '[', ']'));
case _: read_atom(rdr);
}
}
public static function read_str(str:String):MalType {
var tokens = tokenize(str);
if (tokens.length == 0) { throw(new BlankLine()); }
return read_form(new Reader(tokens));
}
}

19
haxe/types/Types.hx Normal file
View File

@ -0,0 +1,19 @@
package types;
enum MalType {
MalNil;
MalTrue;
MalFalse;
MalInt(val:Int);
MalString(val:String);
MalSymbol(val:String);
MalList(val:Array<MalType>);
MalVector(val:Array<MalType>);
}
class Types {
public static function hello() {
trace("hello world");
}
}