aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Grammar.pp2
-rw-r--r--Model/Declaration.php36
-rw-r--r--Model/Variable.php22
-rw-r--r--Visitor/Compiler.php6
-rw-r--r--Visitor/Interpreter.php7
5 files changed, 69 insertions, 4 deletions
diff --git a/Grammar.pp b/Grammar.pp
index 1fe9dd0..3617f51 100644
--- a/Grammar.pp
+++ b/Grammar.pp
@@ -96,6 +96,7 @@
%token default …|default
%token contains contains
%token is is
+%token let let
// Constants.
%token null null|void
@@ -178,6 +179,7 @@ exception:
// NO
#declaration:
+ ( ::let:: #local_declaration )?
extended_identifier() ::colon:: representation()
representation:
diff --git a/Model/Declaration.php b/Model/Declaration.php
index 11c9e4e..373d52a 100644
--- a/Model/Declaration.php
+++ b/Model/Declaration.php
@@ -82,6 +82,13 @@ abstract class Declaration
*/
protected $_predicates = array();
+ /**
+ * Whether declaring a local variable or not.
+ *
+ * @var \Hoa\Praspel\Model\Declaration bool
+ */
+ protected $_let = false;
+
/**
@@ -105,8 +112,13 @@ abstract class Declaration
*/
public function offsetGet ( $offset ) {
- if(false === $this->offsetExists($offset))
- return $this->_variables[$offset] = new Variable($offset, $this);
+ if(false === $this->offsetExists($offset)) {
+
+ $variable = new Variable($offset, $this->_let, $this);
+ $this->_let = false;
+
+ return $this->_variables[$offset] = $variable;
+ }
return $this->_variables[$offset];
}
@@ -143,6 +155,26 @@ abstract class Declaration
}
/**
+ * Allow to write $clause->let['var'] = … to define a local variable (if
+ * $name is not equal to "let", then it is a normal behavior).
+ *
+ * @access public
+ * @param string $name Name.
+ * @return \Hoa\Praspel\Model\Declaration
+ */
+ public function __get ( $name ) {
+
+ if('let' !== $name) {
+
+ return $this->$name;
+ }
+
+ $this->_let = true;
+
+ return $this;
+ }
+
+ /**
* Alias of $this->offsetGet().
*
* @access public
diff --git a/Model/Variable.php b/Model/Variable.php
index 48104f5..06be3dc 100644
--- a/Model/Variable.php
+++ b/Model/Variable.php
@@ -79,6 +79,13 @@ class Variable
protected $_name = null;
/**
+ * Local (let) or not.
+ *
+ * @var \Hoa\Praspel\Model\Variable bool
+ */
+ protected $_local = false;
+
+ /**
* Clause that contains this variable.
*
* @var \Hoa\Praspel\Model\Clause object
@@ -143,13 +150,15 @@ class Variable
*
* @access public
* @param string $name Name.
+ * @param bool $local Local.
* @param \Hoa\Praspel\Model\Clause $clause Clause.
* @return void
* @throw \Hoa\Praspel\Exception\Model
*/
- public function __construct ( $name, Clause $clause ) {
+ public function __construct ( $name, $local, Clause $clause ) {
$this->_name = $name;
+ $this->_local = $local;
$this->_clause = $clause;
$this->_refDomains = &$this->_domains;
@@ -409,6 +418,17 @@ class Variable
}
/**
+ * Check if the variable is local (let) or not.
+ *
+ * @access public
+ * @return bool
+ */
+ public function isLocal ( ) {
+
+ return $this->_local;
+ }
+
+ /**
* Get constraints.
*
* @access public
diff --git a/Visitor/Compiler.php b/Visitor/Compiler.php
index 3159d4f..e8234cf 100644
--- a/Visitor/Compiler.php
+++ b/Visitor/Compiler.php
@@ -115,7 +115,11 @@ class Compiler implements \Hoa\Visitor\Visit {
foreach($element as $name => $var) {
$start = $variable . '[\'' . $name . '\']';
- $out .= $start;
+
+ if(true === $var->isLocal())
+ $out .= $variable . '->let[\'' . $name . '\']';
+ else
+ $out .= $start;
if(null === $alias = $var->getAlias())
$out .= '->in = ' . $var->getDomains() . ';' . "\n";
diff --git a/Visitor/Interpreter.php b/Visitor/Interpreter.php
index c53a1cc..22e66ac 100644
--- a/Visitor/Interpreter.php
+++ b/Visitor/Interpreter.php
@@ -185,6 +185,13 @@ class Interpreter implements \Hoa\Visitor\Visit {
->accept($this, $handle, $eldnah);
break;
+ case '#local_declaration':
+ $variable = $element->getChild(0)
+ ->accept($this, $handle, false);
+ $this->_clause->let[$variable]->in = $element->getChild(1)
+ ->accept($this, $handle, $eldnah);
+ break;
+
case '#qualification':
$children = $element->getChildren();
$variable = $this->_clause[array_shift($children)->accept(