Skip to content

Commit

Permalink
fix merging scopes #43 + unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jcubic committed Sep 17, 2020
1 parent 8a79b0a commit 3c4ec19
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
![LIPS - Scheme Based Powerful Lisp Language](https://github.com/jcubic/lips/blob/devel/assets/lips.svg?raw=true)

[![npm](https://img.shields.io/badge/npm-1.0.0%E2%80%93beta.5-blue.svg)](https://www.npmjs.com/package/@jcubic/lips)
[![travis](https://travis-ci.org/jcubic/lips.svg?branch=devel&f53ffd10debd5b32cc0bc0f62e945f3b5654fd4b)](https://travis-ci.org/jcubic/lips)
[![travis](https://travis-ci.org/jcubic/lips.svg?branch=devel&8a79b0ab4e39edc3cf6c74d74c3251aa8bbeee8f)](https://travis-ci.org/jcubic/lips)
[![Coverage Status](https://coveralls.io/repos/github/jcubic/lips/badge.svg?branch=devel&2c48907438a7265935a7b21e6931008d)](https://coveralls.io/github/jcubic/lips?branch=devel)
[![Join Gitter Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jcubic/lips)
<a href="https://twitter.com/intent/tweet?text=Powerful%20Scheme%20based%20lisp%20language%20written%20in%20JavaScript.%20It%20make%20programmer%20live%20easier%20by%20better%20interaction%20with%20JS.%20Use%20full%20power%20of%20JavaScript,%20lisp%20and%20npm%20to%20create%20your%20applications.&url=https://github.com/jcubic/lips&hashtags=javascript,opensource,lisp,scheme,language,programming">
Expand Down
39 changes: 25 additions & 14 deletions dist/lips.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
* Copyright (c) 2014-present, Facebook, Inc.
* released under MIT license
*
* build: Thu, 17 Sep 2020 10:51:46 +0000
* build: Thu, 17 Sep 2020 16:04:51 +0000
*/
(function () {
'use strict';
Expand Down Expand Up @@ -3138,6 +3138,8 @@
// :: that will show symbols
// ----------------------------------------------------------------------

/* istanbul ignore next */

function symbolize(obj) {
if (obj && _typeof_1(obj) === 'object') {
var result = {};
Expand Down Expand Up @@ -4260,22 +4262,21 @@

function rename(name) {
if (!gensyms[name]) {
var value = scope.get(name, {
throwError: false
});
var gensym_name = gensym(name); // keep names so they can be restored after evaluation
var ref = scope.ref(name);
var gensym_name = gensym(name);

if (ref) {
var value = scope.get(name);
scope.set(gensym_name, value);
} // keep names so they can be restored after evaluation
// if there are free symbols as output
// kind of hack


names.push({
name: name,
gensym: gensym_name
});

if (typeof value !== 'undefined') {
scope.set(gensym_name, value);
}

gensyms[name] = gensym_name;
}

Expand Down Expand Up @@ -8314,7 +8315,17 @@
dynamic_scope = scope;
}

var var_scope = this;
var var_scope = this; // for macros that define variables used in macro (2 levels nestting)

if (var_scope.name === Syntax.merge_env) {
// copy refs for defined gynsyms
var props = Object.getOwnPropertySymbols(var_scope.env);
props.forEach(function (symbol) {
var_scope.parent.set(symbol, var_scope.env[symbol]);
});
var_scope = var_scope.parent;
}

var eval_args = {
env: scope,
dynamic_scope: dynamic_scope,
Expand Down Expand Up @@ -10436,10 +10447,10 @@

var banner = function () {
// Rollup tree-shaking is removing the variable if it's normal string because
// obviously 'Thu, 17 Sep 2020 10:51:46 +0000' == '{{' + 'DATE}}'; can be removed
// obviously 'Thu, 17 Sep 2020 16:04:51 +0000' == '{{' + 'DATE}}'; can be removed
// but disablig Tree-shaking is adding lot of not used code so we use this
// hack instead
var date = LString('Thu, 17 Sep 2020 10:51:46 +0000').valueOf();
var date = LString('Thu, 17 Sep 2020 16:04:51 +0000').valueOf();

var _date = date === '{{' + 'DATE}}' ? new Date() : new Date(date);

Expand Down Expand Up @@ -10476,7 +10487,7 @@
var lips = {
version: 'DEV',
banner: banner,
date: 'Thu, 17 Sep 2020 10:51:46 +0000',
date: 'Thu, 17 Sep 2020 16:04:51 +0000',
exec: exec,
parse: parse,
tokenize: tokenize,
Expand Down
4 changes: 2 additions & 2 deletions dist/lips.min.js

Large diffs are not rendered by default.

19 changes: 15 additions & 4 deletions src/lips.js
Original file line number Diff line number Diff line change
Expand Up @@ -1805,6 +1805,7 @@
// :: debug function that can be used with JSON.stringify
// :: that will show symbols
// ----------------------------------------------------------------------
/* istanbul ignore next */
function symbolize(obj) {
if (obj && typeof obj === 'object') {
var result = {};
Expand Down Expand Up @@ -2646,17 +2647,18 @@
}
function rename(name) {
if (!gensyms[name]) {
var value = scope.get(name, { throwError: false });
var ref = scope.ref(name);
const gensym_name = gensym(name);
if (ref) {
const value = scope.get(name);
scope.set(gensym_name, value);
}
// keep names so they can be restored after evaluation
// if there are free symbols as output
// kind of hack
names.push({
name, gensym: gensym_name
});
if (typeof value !== 'undefined') {
scope.set(gensym_name, value);
}
gensyms[name] = gensym_name;
}
return gensyms[name];
Expand Down Expand Up @@ -5852,6 +5854,15 @@
dynamic_scope = scope;
}
var var_scope = this;
// for macros that define variables used in macro (2 levels nestting)
if (var_scope.name === Syntax.merge_env) {
// copy refs for defined gynsyms
const props = Object.getOwnPropertySymbols(var_scope.env);
props.forEach(symbol => {
var_scope.parent.set(symbol, var_scope.env[symbol]);
});
var_scope = var_scope.parent;
}
var eval_args = { env: scope, dynamic_scope, error };
let ellipsis, rules, symbols;
if (macro.car instanceof LSymbol) {
Expand Down
46 changes: 46 additions & 0 deletions tests/syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -692,3 +692,49 @@
(t.is (to.throw ((lambda (++)
(foo 1 ++ 2)) 10))
true)))

(test "syntax: scope with rewriting"
(lambda (t)
;; ref: https://www.cs.utah.edu/plt/scope-sets/
(define self (letrec-syntax ([identity (syntax-rules ()
[(_ misc-id)
(lambda (x)
(let ([misc-id 'other])
x))])])
(identity x)))
(t.is (self 10) 10)

;; racket macro
(define-syntax define-syntax-rule
(syntax-rules ()
((_ (name args ...) body)
(define-syntax name (syntax-rules () ((name args ...) body))))))

(define-syntax-rule (define-other-five misc-id)
(begin
(define x 5)
misc-id))

(t.is (to.throw (define-other-five x)) true)))

(test "syntax: define syntax macro inside syntax-macro"
(lambda (t)

(define-syntax def (syntax-rules () ((_ x y ) (define x y))))
(define-syntax def-2 (syntax-rules () ((_ x y) (def x y))))

(def foo 10)
(def-2 bar 20)
(t.is (+ foo bar) 30)))

(test_ "syntax: free variables"
(lambda (t)
(define-syntax def (syntax-rules ()
((_ foo bar)
(begin
(define foo bar)
hello))))

(t.is (def hello 10) 10)
(def hello 10)
(t.is hello 10)))

0 comments on commit 3c4ec19

Please sign in to comment.