Merge pull request #1537 from openscad/lc-extensions-cstyle-for
Extend List-Comprehension with c-style for
This commit is contained in:
commit
ee67a842b7
10 changed files with 67 additions and 2 deletions
41
src/expr.cc
41
src/expr.cc
|
|
@ -657,6 +657,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -467,6 +467,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);
|
||||
|
|
|
|||
|
|
@ -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] ]);
|
||||
|
|
|
|||
1
testdata/scad/misc/allexpressions.scad
vendored
1
testdata/scad/misc/allexpressions.scad
vendored
|
|
@ -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] ];
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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]]
|
||||
|
|
|
|||
|
|
@ -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)]];
|
||||
|
|
|
|||
Loading…
Reference in a new issue