Discuss Scratch

Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

BookOwl wrote:

Jonathan50 wrote:

BookOwl wrote:

I golfed it.
It's now just 8 7 lines and 471 433 characters!
That's amazing! But it doesn't work for me, for any input:
-snip-
What's wrong? I've got Python 3.5.1.
Oops, I accidentally removed an escape character, add one more point to my score.
yay! the test program now works:
(print (+ 1 (+ 2 3)))
(print (car (cons 1 nil)))
(print (car (cdr (cons 1 (cons 2 (cons 3 nil))))))
(print (cadr (cons 1 (cons 2 nil))))6
1
2

2
But if you enter nothing and press enter you get an unexpected EOF error. I'm not sure whether or not you'll have to fix that.

Last edited by Jonathan50 (March 19, 2016 23:26:54)

Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

@BookOwl you can shorten
"print":lambda a:print(a)
to
"print":print
to save 12 bytes.

Last edited by Jonathan50 (March 19, 2016 23:38:53)

BookOwl
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

Jonathan50 wrote:

@BookOwl you can shorten
"print":lambda a:print(a)
to
"print":print
to save 12 bytes.
Thanks! Did you decide if I should fix the crashing bug or not?
Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

BookOwl wrote:

Jonathan50 wrote:

@BookOwl you can shorten
"print":lambda a:print(a)
to
"print":print
to save 12 bytes.
Thanks! Did you decide if I should fix the crashing bug or not?
I guess it goes into the rule “It must ignore unnecessary whitespace. (For simplicity, tabs aren't counted as whitespace, programs with tabs may have undefined behaviour.)”.

Last edited by Jonathan50 (March 19, 2016 23:43:24)

BookOwl
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

Jonathan50 wrote:

BookOwl wrote:

Jonathan50 wrote:

@BookOwl you can shorten
"print":lambda a:print(a)
to
"print":print
to save 12 bytes.
Thanks! Did you decide if I should fix the crashing bug or not?
I guess it goes into the rule “It must ignore unnecessary whitespace. (For simplicity, tabs aren't counted as whitespace, programs with tabs may have undefined behaviour.)”.
OK
Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

I slightly improved my REPL at the cost of one byte.
Previously it behaved like:
-> (print "foo")(print "bar")(print "baz")
foo
=> None
bar
=> None
baz
=> None
-> (+ 1 2) (+ 3 4)
=> 3
=> 7
->
Now it only prints the last expression's result, like:
-> (print "foo")(print "bar")(print "baz")
foo
bar
baz
=> None
-> (+ 1 2) (+ 3 4)
=> 7
->
EDIT: claimed it back by using repr(v) instead of v.__repr__()

Last edited by Jonathan50 (March 20, 2016 00:23:13)

Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

@BookOwl
elif p[0]in F:return F[p[0]](*tuple(map(i,p[1:])))
Why do you convert it to a tuple? It works with any iterable AFAIK…

Last edited by Jonathan50 (March 20, 2016 01:25:55)

Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

Updated mine.
Tuples use ‘(’ and ‘)’, like Lisp, so if I use tuples instead of lists I don't have to replace ‘(’
BookOwl
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

Jonathan50 wrote:

@BookOwl
elif p[0]in F:return F[p[0]](*tuple(map(i,p[1:])))
Why do you convert it to a tuple? It works with any iterable AFAIK…
Because otherwise lambda gets mad at me saying that it doesn't like map.
Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

BookOwl wrote:

Jonathan50 wrote:

@BookOwl
elif p[0]in F:return F[p[0]](*tuple(map(i,p[1:])))
Why do you convert it to a tuple? It works with any iterable AFAIK…
Because otherwise lambda gets mad at me saying that it doesn't like map.
What?
BookOwl
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

Do + and * have to handle more than two arguments?
liam48D
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

EDIT: fixed

I'm trying to write a language similar to Lisp with Nearley, for fun, but it's not quite working…

@{%

var ReturnFirst = function(data) {
return data[0];
}

var fns = {
print(args) {
console.log('{Print}', args[0]);
return '<print return>';
},

"+"(args) {
console.log("Add", args);
return args[0] + args[1];
},

cons(args) {
return {car: args[0], cdr: args[1]};
},

car(args) {
return args[0].car;
},

cdr(args) {
return args[0].cdr;
}
};

%}

Program -> Expression:*

@builtin "whitespace.ne"

Expression -> _ "(" _ Function (__ Arguments):? _ ")" _ {%

function(data) {
var name = data[3];
var args = data[4] ? data[4][1].map(function(arg) {
return arg[0];
}) : [];
return fns[name](args);
}

%}

Function -> [^\s]:+ {% function(data) { return data[0].join('') } %}
Arguments -> (_ Argument):* {% function(data) {
return data[0].map(function(e) { return e[1] })
} %}
Argument -> Expression | Number | String

Number -> Decimal {% ReturnFirst %} | Integer {% ReturnFirst %}
Decimal -> Integer "." Integer {% function(data) { return parseFloat(data.join('')) } %}
Integer -> [0-9]:+ {% function(data) { return parseInt(data[0].join('')); } %}
String -> "'" [^']:* "'" {% function(data) { return data[1].join(''); } %}

var program = "[GETS INSERTED]";
var nearley = require('nearley');
var grammar = require('./grammar');
var ans = new nearley.Parser(grammar.ParserRules, grammar.ParserStart)
  .feed(program);
if (ans.results.length) {
  console.log(JSON.stringify(ans.results, null, 2));
} else {
  console.log('No output');
}

If I set program to (print ‘Hello!’), it works:
/*(print 'Hello!')*/

{Print} Hello!

But if I add whitespace around program – i.e. (print ‘Hello!’) , it doesn't work quite right:

/* (print 'Hello!')     */
{Print} Hello!
{Print} Hello!
{Print} Hello!
{Print} Hello!
{Print} Hello!
{Print} Hello!

Any idea what the issue is?

Last edited by liam48D (March 21, 2016 18:00:07)

liam48D
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

Alright, finished mine. It's a nearley grammar, compile and test with the code I showed above (that code doesn't count right?)

@{%

var ReturnFirst = function(data) {
return data[0];
}

var fns = {
print(args) {
console.log('{Print}', args[0]);
return '<print return>';
},

"+"(args) {
return args[0] + args[1];
},

"-"(args) {
return args[0] - args[1];
},

"*"(args) {
return args[0] * args[1];
},

cons(args) {
return {car: args[0], cdr: args[1]};
},

car(args) {
return args[0].car;
},

cdr(args) {
return args[0].cdr;
},

cadr(args) {
return fns.car([fns.cdr([args[0]])]);
}
};

%}

Program -> (_ Expression _):*

@builtin "whitespace.ne"

Expression -> "(" _ Function (__ Arguments):? _ ")" {%

function(data) {
var name = data[2];
var args = data[3] ? data[3][1].map(function(arg) {
return arg[0];
}) : [];

// console.log('Calling', name, 'with args', args);

return fns[name](args);
}

%}

Function -> [^\s]:+ {% function(data) { return data[0].join('') } %}
Arguments -> (_ Argument):* {% function(data) {
return data[0].map(function(e) { return e[1] })
} %}
Argument -> Expression | Number | String | Nil

Number -> Decimal {% ReturnFirst %} | Integer {% ReturnFirst %}
Decimal -> Integer "." Integer {% function(data) { return parseFloat(data.join('')) } %}
Integer -> [0-9]:+ {% function(data) { return parseInt(data[0].join('')); } %}
Nil -> "nil" {% function() { return null; } %}
String -> "'" [^']:* "'" {% function(data) { return data[1].join(''); } %}

It can easily be golfed a fair but but.. readable code is better.

(Are you guys having any troubles with the 60 second rule today?)
Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

BookOwl wrote:

Do + and * have to handle more than two arguments?
No. They can but it is not required.
BookOwl
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

Jonathan50 wrote:

BookOwl wrote:

Do + and * have to handle more than two arguments?
No. They can but it is not required.
OK. I can use that to save a few bytes (I think)
Jonathan50
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

liam48D wrote:

Alright, finished mine. It's a nearley grammar, compile and test with the code I showed above (that code doesn't count right?)

-snip-

It can easily be golfed a fair but but.. readable code is better.

(Are you guys having any troubles with the 60 second rule today?)
(You have [scratchblocks] at the end of your post ಠ_ಠ ಠ_ಠ)
Sorry, it does count. You need to make an implementation, not just a parser
bobbybee
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

Jonathan50 wrote:

liam48D wrote:

Alright, finished mine. It's a nearley grammar, compile and test with the code I showed above (that code doesn't count right?)

-snip-

It can easily be golfed a fair but but.. readable code is better.

(Are you guys having any troubles with the 60 second rule today?)
(You have [scratchblocks] at the end of your post ಠ_ಠ ಠ_ಠ)
Sorry, it does count. You need to make an implementation, not just a parser

It is an implementation, abusing the Turing-completeness of the (amazing) nearley parser.
BookOwl
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

I golfed my version to just 4 lines and 321 characters!
Here it is:
import re
from operator import *
i=lambda p: p if type(p)!=tuple else{"cons":lambda a,b:(a,b),"car":lambda a:a[0],"cdr":lambda a:a[1],"cadr":lambda a:a[1][0],"+":add,"-":sub,"*":mul,"print":print}[p[0]](*map(i,p[1:]))
while 1:i(eval(re.sub("[\n ]+",",",re.sub("[a-z+\-*]+","'\g<0>'",input()).replace("'nil'","''"))or"''"))
liam48D
Scratcher
1000+ posts

Code golf - tiniest Lisp-like language

bobbybee wrote:

Jonathan50 wrote:

liam48D wrote:

Alright, finished mine. It's a nearley grammar, compile and test with the code I showed above (that code doesn't count right?)

-snip-

It can easily be golfed a fair but but.. readable code is better.

(Are you guys having any troubles with the 60 second rule today?)
(You have [scratchblocks] at the end of your post ಠ_ಠ ಠ_ಠ)
Sorry, it does count. You need to make an implementation, not just a parser

It is an implementation, abusing the Turing-completeness of the (amazing) nearley parser.
Yep! ^^^

Powered by DjangoBB