aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-11-03 23:50:55 -0600
committerJoel Martin <github@martintribe.org>2015-01-09 16:16:45 -0600
commit9b3362e86a57ed7f14c5fd018c37713185e0c154 (patch)
tree4f9adce9df9d08401bfc260ec10e6709a55a8b57
parentf947d503f748fd1218f502ef1394ff9e28175ef8 (diff)
downloadmal-9b3362e86a57ed7f14c5fd018c37713185e0c154.tar.gz
mal-9b3362e86a57ed7f14c5fd018c37713185e0c154.zip
R: add time-ms. Readline history. Misc cleanups.
-rw-r--r--.gitignore1
-rw-r--r--README.md13
-rw-r--r--docs/TODO19
-rw-r--r--r/core.r1
-rw-r--r--r/readline.r34
-rw-r--r--r/step9_try.r6
-rw-r--r--r/stepA_interop.r6
7 files changed, 67 insertions, 13 deletions
diff --git a/.gitignore b/.gitignore
index ed67933..387be2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,4 @@ rust/target/
rust/mal
rust/Cargo.lock
rust/.cargo
+r/lib
diff --git a/README.md b/README.md
index adcdeb6..208380f 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
## Description
Mal is an interpreter for a subset of the Clojure programming
-language. Mal is implemented from scratch in 15 different languages:
+language. Mal is implemented from scratch in 16 different languages:
* Bash shell
* C
@@ -18,6 +18,7 @@ language. Mal is implemented from scratch in 15 different languages:
* PHP
* Postscript
* Python
+* R
* Ruby
* Rust
@@ -173,6 +174,16 @@ cd python
python stepX_YYY.py
```
+### R
+
+The R implementation of mal requires R (r-base-core) to run.
+
+```
+cd r
+make libs
+Rscript stepX_YYY.rb
+```
+
### Ruby (1.8)
```
diff --git a/docs/TODO b/docs/TODO
index 6f047c3..f4efd32 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -64,6 +64,10 @@ Python:
- error: python ../python/stepA_interop.py ../mal/stepA_interop.mal ../mal/stepA_interop.mal
- interop tests
+R:
+ - readline history
+ - tracebacks in errors
+
Ruby:
@@ -90,6 +94,11 @@ Future Implementations:
- http://stackoverflow.com/questions/23942627/does-rust-0-10-have-a-rl-package
- http://blog.skylight.io/rust-means-never-having-to-close-a-socket/
+ - R
+ - https://stat.ethz.ch/R-manual/R-devel/library/base/html/readline.html
+ - http://dssm.unipa.it/CRAN/web/packages/rdyncall/rdyncall.pdf
+ - http://www.dyncall.org/docs/FFI.pdf
+
- Redmonk languages from Jan 2014:
http://sogrady-media.redmonk.com/sogrady/files/2014/01/lang-rank-114-wm.png
@@ -97,24 +106,24 @@ Future Implementations:
* JavaScript
* Java
* PHP
- * C#
* Python
+ * C#
- C++
* Ruby
* C
- Objective-C
- * Perl
* Shell (Bash 4)
+ * Perl
- Tier 2
- R
- Scala
- Haskell
- * Clojure
- - CoffeeScript
- Visual Basic
+ - CoffeeScript
+ * Clojure
- Groovy
- - Go
+ * Go
- Lua
- Erlang
- Emacs Lisp
diff --git a/r/core.r b/r/core.r
index d0443b0..74c8f6d 100644
--- a/r/core.r
+++ b/r/core.r
@@ -137,6 +137,7 @@ core_ns <- list(
"-"=function(a,b) a-b,
"*"=function(a,b) a*b,
"/"=function(a,b) a/b,
+ "time-ms"=function() round(as.numeric(Sys.time())*1000),
"list"=new.list,
"list?"=function(a) .list_q(a),
diff --git a/r/readline.r b/r/readline.r
index b842c2b..79ababc 100644
--- a/r/readline.r
+++ b/r/readline.r
@@ -1,16 +1,40 @@
..readline.. <- TRUE
+HISTORY_FILE = paste(path.expand("~"), "/.mal-history", sep="")
+
library(rdyncall, lib.loc="lib/")
-#rllib <- dynfind(c("edit"))
-rllib <- dynfind(c("readline"))
-rl <- .dynsym(rllib,"readline")
+#.rllib <- dynfind(c("edit"))
+.rllib <- dynfind(c("readline"))
+.call_readline <- .dynsym(.rllib,"readline")
+.call_add_history <- .dynsym(.rllib,"add_history")
-readline <- function(prompt) {
- res <- .dyncall(rl, "Z)p", prompt)
+.state <- new.env()
+.state$rl_history_loaded = FALSE
+
+.readline <- function(prompt) {
+ res <- .dyncall(.call_readline, "Z)p", prompt)
if (is.nullptr(res)) {
return(NULL)
} else {
return(ptr2str(res))
}
}
+
+readline <- function(prompt) {
+ if (!.state$rl_history_loaded) {
+ .state$rl_history_loaded <- TRUE
+
+ lines <- scan(HISTORY_FILE, what="", sep="\n", quiet=TRUE)
+ for(add_line in lines) {
+ .dyncall(.call_add_history, "Z)v", add_line)
+ }
+ }
+
+ line <- .readline(prompt)
+ if (is.null(line)) return(NULL)
+ .dyncall(.call_add_history, "Z)v", line)
+ write(line, file=HISTORY_FILE, append=TRUE)
+
+ line
+}
diff --git a/r/step9_try.r b/r/step9_try.r
index b37fe38..e699048 100644
--- a/r/step9_try.r
+++ b/r/step9_try.r
@@ -176,7 +176,11 @@ Env.set(repl_env, "*ARGV*", new.list())
args <- commandArgs(trailingOnly = TRUE)
if (length(args) > 0) {
Env.set(repl_env, "*ARGV*", new.listl(slice(list(args),2)))
- . <- rep(concat("(load-file \"", args[[1]], "\")"))
+ tryCatch({
+ . <- rep(concat("(load-file \"", args[[1]], "\")"))
+ }, error=function(err) {
+ cat("Error: ", get_error(err),"\n", sep="")
+ })
quit(save="no", status=0)
}
diff --git a/r/stepA_interop.r b/r/stepA_interop.r
index b37fe38..e699048 100644
--- a/r/stepA_interop.r
+++ b/r/stepA_interop.r
@@ -176,7 +176,11 @@ Env.set(repl_env, "*ARGV*", new.list())
args <- commandArgs(trailingOnly = TRUE)
if (length(args) > 0) {
Env.set(repl_env, "*ARGV*", new.listl(slice(list(args),2)))
- . <- rep(concat("(load-file \"", args[[1]], "\")"))
+ tryCatch({
+ . <- rep(concat("(load-file \"", args[[1]], "\")"))
+ }, error=function(err) {
+ cat("Error: ", get_error(err),"\n", sep="")
+ })
quit(save="no", status=0)
}