From a5f2a15ec038af66c5cbce819a24c0917afe0740 Mon Sep 17 00:00:00 2001 From: "Brian T. Rice" Date: Sat, 1 Jan 2011 20:11:22 -0800 Subject: [PATCH] Added a Binding Syntax node and implemented bindTo: to use it, enforcing immutable local bindings. Bindings inside blocks will automatically create local variables in the outermost block scope without a variable or binding of that name. --- src/lib/macro.slate | 13 +++++++++++-- src/syntax/node.slate | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/lib/macro.slate b/src/lib/macro.slate index baa2553..4cfbf96 100644 --- a/src/lib/macro.slate +++ b/src/lib/macro.slate @@ -172,8 +172,17 @@ node@(nodes LoadVariable traits) bindTo: value &environment: env msg@(nodes UnaryMessage traits) bindTo: value &environment: env [ - nodes KeywordMessage sending: #bind:to: to: - {msg arguments first. nodes Literal for: msg selector. value} + env + ifNil: + [nodes KeywordMessage sending: #bind:to: to: + {msg arguments first. nodes Literal for: msg selector. value}] + ifNotNil: + [(env outermostScopeNotBinding: msg selector) + ifNil: [error: 'Cannot rebind'] + ifNotNilDo: + [| :scope | + StoreVariable of: value into: + (scope addVariable: (nodes Binding named: msg selector))]] ]. message@(nodes KeywordMessage traits) bindTo: val diff --git a/src/syntax/node.slate b/src/syntax/node.slate index 8a85e44..f8ee6d5 100644 --- a/src/syntax/node.slate +++ b/src/syntax/node.slate @@ -698,6 +698,21 @@ a Namespace." scope ]. +block@(nodes Block traits) hasVariableNamed: name +[ + block localVariables anySatisfy: [| :var | name =~ var name] +]. + +block@(nodes Block traits) outermostScopeNotBinding: name +"Answers the outermost scope that does not have a given binding or slot." +[| scope | + (block hasVariableNamed: name) ifFalse: + [scope := block. + [(scope hasVariableNamed: name) \/ [scope parentScope isSameAs: nodes Namespace]] + whileFalse: [scope := scope parentScope]]. + scope +]. + block@(nodes Block traits) findVariable: name "Searches through the current scope, and then upward, for the entry corresponding to the given name, and answers what it can find, or Nil if none." @@ -963,6 +978,12 @@ var@(nodes Variable traits) deepCopy: scope scope findVariable: var name ]. +var@(nodes Variable traits) isImmutable [False]. + +nodes define: #Binding &parents: {nodes Variable}. + +var@(nodes Binding traits) isImmutable [True]. + nodes define: #RestVariable &parents: {nodes Variable}. nodes define: #VariableOperation &parents: {nodes Node} &slots: {#variable}. @@ -1003,6 +1024,9 @@ store@(nodes StoreVariable traits) of: value into: variable var@(nodes Variable traits) store: value [nodes StoreVariable of: value into: var]. +var@(nodes Binding traits) store: value +[error: 'Cannot rebind']. + load@(nodes LoadVariable traits) store: value [load variable store: value]. -- 2.11.4.GIT