Merge branch 'master' into openscadapp

This commit is contained in:
Marius Kintel 2016-01-25 22:20:20 -05:00
commit 930896ed99
10 changed files with 67 additions and 2 deletions

View file

@ -647,6 +647,47 @@ void ExpressionLcFor::print(std::ostream &stream) const
stream << "for(" << this->call_arguments << ") (" << *this->first << ")";
}
ExpressionLcForC::ExpressionLcForC(const AssignmentList &arglist, const AssignmentList &incrargs, Expression *cond, Expression *expr)
: ExpressionLc(cond, expr), call_arguments(arglist), incr_arguments(incrargs)
{
}
ValuePtr ExpressionLcForC::evaluate(const Context *context) const
{
ExperimentalFeatureException::check(Feature::ExperimentalForCExpression);
Value::VectorType vec;
Context c(context);
evaluate_sequential_assignment(this->call_arguments, &c);
unsigned int counter = 0;
while (this->first->evaluate(&c)) {
vec.push_back(this->second->evaluate(&c));
if (counter++ == 1000000) throw RecursionException::create("for loop", "");
Context tmp(&c);
evaluate_sequential_assignment(this->incr_arguments, &tmp);
c.apply_variables(tmp);
}
if (this->second->isListComprehension()) {
return ValuePtr(flatten(vec));
} else {
return ValuePtr(vec);
}
}
void ExpressionLcForC::print(std::ostream &stream) const
{
stream
<< "for(" << this->call_arguments
<< ";" << *this->first
<< ";" << this->incr_arguments
<< ") " << *this->second;
}
ExpressionLcLet::ExpressionLcLet(const AssignmentList &arglist, Expression *expr)
: ExpressionLc(expr), call_arguments(arglist)
{

View file

@ -259,6 +259,17 @@ private:
AssignmentList call_arguments;
};
class ExpressionLcForC : public ExpressionLc
{
public:
ExpressionLcForC(const AssignmentList &arglist, const AssignmentList &incrargs, Expression *cond, Expression *expr);
ValuePtr evaluate(const class Context *context) const;
virtual void print(std::ostream &stream) const;
private:
AssignmentList call_arguments;
AssignmentList incr_arguments;
};
class ExpressionLcEach : public ExpressionLc
{
public:

View file

@ -21,6 +21,7 @@ Feature::list_t Feature::feature_list;
*/
const Feature Feature::ExperimentalEachExpression("lc-each", "Enable <code>each</code> expression in list comprehensions.");
const Feature Feature::ExperimentalElseExpression("lc-else", "Enable <code>else</code> expression in list comprehensions.");
const Feature Feature::ExperimentalForCExpression("lc-for-c", "Enable C-style <code>for</code> expression in list comprehensions.");
Feature::Feature(const std::string &name, const std::string &description)
: enabled(false), name(name), description(description)

View file

@ -16,6 +16,7 @@ public:
static const Feature ExperimentalEachExpression;
static const Feature ExperimentalElseExpression;
static const Feature ExperimentalForCExpression;
const std::string& get_name() const;
const std::string& get_description() const;

View file

@ -468,6 +468,12 @@ list_comprehension_elements:
}
delete $3;
}
| TOK_FOR '(' arguments_call ';' expr ';' arguments_call ')' list_comprehension_elements_or_expr
{
$$ = new ExpressionLcForC(*$3, *$7, $5, $9);
delete $3;
delete $7;
}
| TOK_IF '(' expr ')' list_comprehension_elements_or_expr
{
$$ = new ExpressionLcIf($3, $5, 0);

View file

@ -6,3 +6,5 @@ echo([ for (a = [0 : 3]) if (a < 2) ( if (a < 1) ["+", a] ) else ["-", a] ]);
echo([ for (a = [2 : 4]) each [ a, a*a ] ]);
function f() = [ for (a = [0 : 4]) pow(2, a) ];
echo([ each ["a", "b"], each [-5 : -2 : -9], each f(), each "c", each 42, each true ]);
echo([ for (i=2;i<=10;i=i+2) i ]);
echo([ for (i=1,n=1;i<=4;i=i+1,n=(n+i)*i) [i,n] ]);

View file

@ -34,3 +34,4 @@ ee = ["abc", for (a=[0,1]) let(b=a) if (true) b, true, for(c=[1:3]) c, 3];
ff = [for (a=[0,1]) if (a == 0) "A" else ( "B" )];
gg = [each [ "a", 0, false ]];
hh = [for (a = [0 : 3]) if (a < 2) ( if (a < 1) ["+", a] ) else ["-", a] ];
ii = [for (a=0,b=1;a < 5;a=a+1,b=b+2) [a,b*b] ];

View file

@ -997,7 +997,7 @@ function(add_cmdline_test TESTCMD_BASENAME)
if (${EXPERIMENTAL} EQUAL -1)
set(EXPERIMENTAL_OPTION "")
else()
set(EXPERIMENTAL_OPTION "--enable=lc-each" "--enable=lc-else")
set(EXPERIMENTAL_OPTION "--enable=lc-each" "--enable=lc-else" "--enable=lc-for-c")
endif()
# 2D tests should be viewed from the top, not an angle.

View file

@ -5,3 +5,5 @@ ECHO: [["+", 0], ["-", 1]]
ECHO: [["+", 0], ["-", 2], ["-", 3]]
ECHO: [2, 4, 3, 9, 4, 16]
ECHO: ["a", "b", -5, -7, -9, 1, 2, 4, 8, 16, "c", 42, true]
ECHO: [2, 4, 6, 8, 10]
ECHO: [[1, 1], [2, 6], [3, 27], [4, 124]]

View file

@ -34,4 +34,4 @@ ee = ["abc", for(a = [0, 1]) (let(b = a) (if(true) (b))), true, for(c = [1 : 3])
ff = [for(a = [0, 1]) (if((a == 0)) ("A") else ("B"))];
gg = [each (["a", 0, false])];
hh = [for(a = [0 : 3]) (if((a < 2)) (if((a < 1)) (["+", a])) else (["-", a]))];
ii = [for(a = 0, b = 1;(a < 5);a = (a + 1), b = (b + 2)) [a, (b * b)]];