M include/scopes/scopes.h +1 -3
@@ 237,9 237,7 @@ SCOPES_LIBEXPORT sc_symbol_raises_t sc_g
SCOPES_LIBEXPORT sc_valueref_t sc_global_string_new(const char *ptr, size_t count);
SCOPES_LIBEXPORT sc_valueref_t sc_global_string_new_from_cstr(const char *ptr);
-SCOPES_LIBEXPORT sc_valueref_t sc_if_new();
-SCOPES_LIBEXPORT void sc_if_append_then_clause(sc_valueref_t value, sc_valueref_t cond, sc_valueref_t body);
-SCOPES_LIBEXPORT void sc_if_append_else_clause(sc_valueref_t value, sc_valueref_t body);
+SCOPES_LIBEXPORT sc_valueref_t sc_cond_new(sc_valueref_t cond, sc_valueref_t then_value, sc_valueref_t else_value);
SCOPES_LIBEXPORT sc_valueref_t sc_switch_new(sc_valueref_t expr);
SCOPES_LIBEXPORT void sc_switch_append_case(sc_valueref_t value, sc_valueref_t literal, sc_valueref_t body);
M lib/scopes/core.sc +20 -23
@@ 2008,14 2008,11 @@ fn dispatch-and-or (args flip)
return call-elsef
else
return thenargs
- let ifval = (sc_if_new)
- if flip
- sc_if_append_then_clause ifval condbool call-elsef
- sc_if_append_else_clause ifval thenargs
- else
- sc_if_append_then_clause ifval condbool thenargs
- sc_if_append_else_clause ifval call-elsef
- ifval
+ sc_cond_new condbool
+ if flip
+ _ call-elsef thenargs
+ else
+ _ thenargs call-elsef
let safe-shl =
spice-macro
@@ 4610,13 4607,14 @@ let packedtupleof = (gen-tupleof sc_pack
fn (args)
let self = ('getarg args 0)
let other = ('getarg args 1)
- let block = (sc_if_new)
- for i in (range ('element-count ('typeof self)))
- sc_if_append_then_clause block
- `((self @ i) != (other @ i))
- `false
- sc_if_append_else_clause block `true
- block
+ loop (i result = ('element-count ('typeof self)) `true)
+ if (i == 0)
+ break result
+ let i = (i - 1)
+ _ i
+ sc_cond_new `((self @ i) != (other @ i))
+ `false
+ result
__unpack = __unpack-aggregate
__countof = __countof-aggregate
__@ =
@@ 7339,15 7337,14 @@ fn constructor (cls args...)
spice tuple== (self other)
let cls = ('typeof self)
let numfields = ('element-count cls)
- let block = (sc_if_new)
let quoted-false = `false
- loop (i = 0)
- if (i == numfields)
- break;
- sc_if_append_then_clause block `((@ self i) != (@ other i)) quoted-false
- i + 1
- sc_if_append_else_clause block `true
- block
+ loop (i result = numfields `true)
+ if (i == 0)
+ break result
+ let i = (i - 1)
+ _ i
+ sc_cond_new `((self @ i) != (other @ i)) quoted-false result
+
typedef+ tuple
spice-quote
M src/expander.cpp +22 -18
@@ 837,10 837,23 @@ struct Expander {
branches.push_back(EOL);
}
- auto ifexpr = If::from();
+ ValueRef result;
- int lastidx = (int)branches.size() - 1;
- for (int idx = 0; idx < lastidx; ++idx) {
+ const int lastidx = (int)branches.size() - 1;
+ it = branches[lastidx];
+ if (it == EOL) {
+ result = ValueRef(ref(anchor, ArgumentList::from({})));
+ } else {
+ auto else_anchor = it->at.anchor();
+ it = it->next;
+ Expander subexp(Scope::from(nullptr, env), astscope);
+
+ result = SCOPES_GET_RESULT(
+ subexp.expand_expression(ref(else_anchor, it), false));
+ }
+
+ int idx = lastidx;
+ while (idx-- > 0) {
it = branches[idx];
//const Anchor *anchor = it->at->anchor();
SCOPES_CHECK_RESULT(verify_list_parameter_count("branch", it, 1, -1));
@@ 873,24 886,15 @@ struct Expander {
env = subexp.env;
subexp.env = Scope::from(nullptr, env);
- ifexpr->append_then(cond,
- SCOPES_GET_RESULT(
- subexp.expand_expression(ref(branch_anchor, it), false)));
+ result =
+ ref(branch_anchor, CondTemplate::from(cond,
+ SCOPES_GET_RESULT(
+ subexp.expand_expression(ref(branch_anchor, it), false)),
+ result));
}
}
- it = branches[lastidx];
- if (it != EOL) {
- auto else_anchor = it->at.anchor();
- it = it->next;
- Expander subexp(Scope::from(nullptr, env), astscope);
-
- ifexpr->append_else(
- SCOPES_GET_RESULT(
- subexp.expand_expression(ref(else_anchor, it), false)));
- }
-
- return ValueRef(ref(anchor, ifexpr));
+ return ValueRef(ref(anchor, result));
}
static SCOPES_RESULT(bool) get_kwargs(
M src/globals.cpp +3 -13
@@ 1448,17 1448,9 @@ sc_valueref_t sc_global_string_new_from_
return GlobalString::from(ptr, strlen(ptr));
}
-sc_valueref_t sc_if_new() {
- using namespace scopes;
- return If::from();
-}
-void sc_if_append_then_clause(sc_valueref_t value, sc_valueref_t cond, sc_valueref_t body) {
+sc_valueref_t sc_cond_new(sc_valueref_t cond, sc_valueref_t then_value, sc_valueref_t else_value) {
using namespace scopes;
- value.cast<If>()->append_then(cond, body);
-}
-void sc_if_append_else_clause(sc_valueref_t value, sc_valueref_t body) {
- using namespace scopes;
- value.cast<If>()->append_else(body);
+ return CondTemplate::from(cond, then_value, else_value);
}
sc_valueref_t sc_switch_new(sc_valueref_t expr) {
@@ 2375,9 2367,7 @@ void init_globals(int argc, char *argv[]
DEFINE_RAISING_EXTERN_C_FUNCTION(sc_global_storage_class, TYPE_Symbol, TYPE_ValueRef);
DEFINE_EXTERN_C_FUNCTION(sc_global_string_new, TYPE_ValueRef, native_ro_pointer_type(TYPE_I8), TYPE_USize);
DEFINE_EXTERN_C_FUNCTION(sc_global_string_new_from_cstr, TYPE_ValueRef, native_ro_pointer_type(TYPE_I8));
- DEFINE_EXTERN_C_FUNCTION(sc_if_new, TYPE_ValueRef);
- DEFINE_EXTERN_C_FUNCTION(sc_if_append_then_clause, _void, TYPE_ValueRef, TYPE_ValueRef, TYPE_ValueRef);
- DEFINE_EXTERN_C_FUNCTION(sc_if_append_else_clause, _void, TYPE_ValueRef, TYPE_ValueRef);
+ DEFINE_EXTERN_C_FUNCTION(sc_cond_new, TYPE_ValueRef, TYPE_ValueRef, TYPE_ValueRef, TYPE_ValueRef);
DEFINE_EXTERN_C_FUNCTION(sc_switch_new, TYPE_ValueRef, TYPE_ValueRef);
DEFINE_EXTERN_C_FUNCTION(sc_switch_append_case, _void, TYPE_ValueRef, TYPE_ValueRef, TYPE_ValueRef);
DEFINE_EXTERN_C_FUNCTION(sc_switch_append_pass, _void, TYPE_ValueRef, TYPE_ValueRef, TYPE_ValueRef);
M src/globals.hpp +1 -3
@@ 67,9 67,7 @@ namespace scopes {
T(g_sc_expression_new, "sc_expression_new") \
T(g_sc_expression_append, "sc_expression_append") \
T(g_sc_expression_set_scoped, "sc_expression_set_scoped") \
- T(g_sc_if_new, "sc_if_new") \
- T(g_sc_if_append_then_clause, "sc_if_append_then_clause") \
- T(g_sc_if_append_else_clause, "sc_if_append_else_clause") \
+ T(g_sc_cond_new, "sc_cond_new") \
T(g_sc_switch_new, "sc_switch_new") \
T(g_sc_switch_append_case, "sc_switch_append_case") \
T(g_sc_switch_append_pass, "sc_switch_append_pass") \
M src/prover.cpp +32 -57
@@ 3509,67 3509,42 @@ static SCOPES_RESULT(TypedValueRef) prov
return finalize_merge_label(ctx, merge_label, "switch case");
}
-static SCOPES_RESULT(TypedValueRef) prove_If(const ASTContext &ctx, const IfRef &_if) {
+static SCOPES_RESULT(TypedValueRef) prove_CondTemplate(const ASTContext &ctx, const CondTemplateRef &node) {
SCOPES_RESULT_TYPE(TypedValueRef);
- assert(!_if->clauses.empty());
- int numclauses = _if->clauses.size();
- assert(numclauses >= 1);
- CondBrRef first_condbr;
- CondBrRef last_condbr;
- LabelRef merge_label = make_merge_label(ctx, _if.anchor());
+ LabelRef merge_label = make_merge_label(ctx, node.anchor());
ASTContext subctx = ctx.with_block(merge_label->body);
- for (int i = 0; i < numclauses; ++i) {
- auto &&clause = _if->clauses[i];
- //assert(clause.anchor);
- //SCOPES_ANCHOR(clause.anchor);
- if (clause.is_then()) {
- TypedValueRef newcond = SCOPES_GET_RESULT(prove(subctx, clause.cond));
- {
- SCOPES_TRACE_PROVE_ARG(newcond);
- newcond = ref(newcond.anchor(),
- ExtractArgument::from(newcond, 0));
- SCOPES_CHECK_RESULT(build_tobool(subctx, clause.cond.anchor(), newcond));
- SCOPES_CHECK_RESULT(build_deref_automove(subctx, newcond, newcond));
- auto condT = strip_qualifiers(newcond->get_type());
- if (condT != TYPE_Bool) {
- SCOPES_ERROR(ConditionNotBool, newcond->get_type());
- }
- }
- CondBrRef condbr = ref(newcond.anchor(), CondBr::from(newcond));
- if (!first_condbr) {
- first_condbr = condbr;
- merge_label->splitpoints.insert(condbr.unref());
- }
- condbr->then_body.set_parent(&merge_label->body);
- condbr->else_body.set_parent(&merge_label->body);
- auto thenctx = subctx.with_block(condbr->then_body);
- auto thenresult = SCOPES_GET_RESULT(prove(thenctx, clause.value));
- if (is_returning(thenresult->get_type())) {
- SCOPES_CHECK_RESULT(make_merge(thenctx, thenresult.anchor(), merge_label, thenresult));
- }
- if (last_condbr) {
- last_condbr->else_body.append(condbr);
- } else {
- merge_label->body.append(condbr);
- }
- last_condbr = condbr;
- subctx = subctx.with_block(condbr->else_body);
- } else {
- assert(last_condbr);
- auto elseresult = SCOPES_GET_RESULT(prove(subctx, clause.value));
- if (is_returning(elseresult->get_type())) {
- ASTContext elsectx = ctx.with_block(last_condbr->else_body);
- SCOPES_CHECK_RESULT(make_merge(elsectx, _if.anchor(), merge_label, elseresult));
- }
- last_condbr = CondBrRef();
+ //assert(clause.anchor);
+ //SCOPES_ANCHOR(clause.anchor);
+ TypedValueRef newcond = SCOPES_GET_RESULT(prove(subctx, node->cond));
+ {
+ SCOPES_TRACE_PROVE_ARG(newcond);
+ newcond = ref(newcond.anchor(),
+ ExtractArgument::from(newcond, 0));
+ SCOPES_CHECK_RESULT(build_tobool(subctx, node->cond.anchor(), newcond));
+ SCOPES_CHECK_RESULT(build_deref_automove(subctx, newcond, newcond));
+ auto condT = strip_qualifiers(newcond->get_type());
+ if (condT != TYPE_Bool) {
+ SCOPES_ERROR(ConditionNotBool, newcond->get_type());
}
}
- if (last_condbr) {
- // last else value missing
- ASTContext elsectx = ctx.with_block(last_condbr->else_body);
- SCOPES_CHECK_RESULT(make_merge(elsectx, _if.anchor(), merge_label,
- ref(_if.anchor(), ArgumentList::from({}))));
+ CondBrRef condbr = ref(newcond.anchor(), CondBr::from(newcond));
+ merge_label->splitpoints.insert(condbr.unref());
+ condbr->then_body.set_parent(&merge_label->body);
+ condbr->else_body.set_parent(&merge_label->body);
+ auto thenctx = subctx.with_block(condbr->then_body);
+ auto thenresult = SCOPES_GET_RESULT(prove(thenctx, node->then_value));
+ if (is_returning(thenresult->get_type())) {
+ SCOPES_CHECK_RESULT(make_merge(thenctx, thenresult.anchor(), merge_label, thenresult));
+ }
+ merge_label->body.append(condbr);
+
+ subctx = subctx.with_block(condbr->else_body);
+
+ auto elseresult = SCOPES_GET_RESULT(prove(subctx, node->else_value));
+ if (is_returning(elseresult->get_type())) {
+ ASTContext elsectx = ctx.with_block(condbr->else_body);
+ SCOPES_CHECK_RESULT(make_merge(elsectx, node.anchor(), merge_label, elseresult));
}
if (merge_label->merges.empty()) {
@@ 3577,7 3552,7 @@ static SCOPES_RESULT(TypedValueRef) prov
// conditions do not need a merge label
assert(ctx.block);
ctx.merge_block(merge_label->body);
- return TypedValueRef(first_condbr);
+ return TypedValueRef(condbr);
}
return finalize_merge_label(ctx, merge_label, "branch");
M src/quote.cpp +6 -15
@@ 230,23 230,14 @@ struct Quoter {
return canonicalize(expr);
}
- SCOPES_RESULT(ValueRef) quote_If(int level, const IfRef &node) {
+ SCOPES_RESULT(ValueRef) quote_CondTemplate(int level, const CondTemplateRef &node) {
SCOPES_RESULT_TYPE(ValueRef);
auto _anchor = node.anchor();
- auto value = REF(CallTemplate::from(g_sc_if_new, {}));
- auto expr = REF(Expression::unscoped_from());
- for (auto &&clause : node->clauses) {
- if (clause.is_then()) {
- expr->append(REF(CallTemplate::from(g_sc_if_append_then_clause, { value,
- SCOPES_GET_RESULT(quote(level, clause.cond)),
- SCOPES_GET_RESULT(quote(level, clause.value)) })));
- } else {
- expr->append(REF(CallTemplate::from(g_sc_if_append_else_clause, { value,
- SCOPES_GET_RESULT(quote(level, clause.value)) })));
- }
- }
- expr->append(value);
- return canonicalize(expr);
+ return ValueRef(REF(CallTemplate::from(g_sc_cond_new, {
+ SCOPES_GET_RESULT(quote(level, node->cond)),
+ SCOPES_GET_RESULT(quote(level, node->then_value)),
+ SCOPES_GET_RESULT(quote(level, node->else_value))
+ })));
}
SCOPES_RESULT(ValueRef) quote_Template(int level, const TemplateRef &node) {
M src/stream_expr.cpp +4 -11
@@ 411,18 411,11 @@ HANDLER(Unquote) {
);
}
-HANDLER(If) {
+HANDLER(CondTemplate) {
auto _anchor = node.anchor();
const List *l = EOL;
- int i = node->clauses.size();
- while (i-- > 0) {
- auto clause = node->clauses[i];
- if (clause.cond) {
- l = List::from(LIST(SYMBOL(KW_Case), clause.cond, clause.value), l);
- } else {
- l = List::from(LIST(SYMBOL(KW_Default), clause.value), l);
- }
- }
+ l = List::from(LIST(SYMBOL(KW_Case), node->cond, node->then_value), l);
+ l = List::from(LIST(SYMBOL(KW_Default), node->else_value), l);
l = List::from(SYMBOL(KW_If), l);
return ValueRef(_anchor, ConstPointer::list_from(l));
}
@@ 508,7 501,7 @@ ValueRef _convert(const ValueRef &node)
//CASE_HANDLER(Call)
CASE_HANDLER(Template)
CASE_HANDLER(Global)
- CASE_HANDLER(If)
+ CASE_HANDLER(CondTemplate)
CASE_HANDLER(ParameterTemplate)
CASE_HANDLER(Expression)
CASE_HANDLER(LabelTemplate)
M src/value.cpp +7 -24
@@ 948,32 948,15 @@ CondBrRef CondBr::from(const TypedValueR
//------------------------------------------------------------------------------
-bool If::Clause::is_then() const {
- return cond.unref() != nullptr;
-}
-
-If::If(const Clauses &_clauses)
- : UntypedValue(VK_If), clauses(_clauses) {
-}
-
-IfRef If::from(const Clauses &_clauses) {
- return ref(unknown_anchor(), new If(_clauses));
+CondTemplate::CondTemplate(
+ const ValueRef &_cond, const ValueRef &_then_value, const ValueRef &_else_value)
+ : UntypedValue(VK_CondTemplate),
+ cond(_cond), then_value(_then_value), else_value(_else_value) {
}
-void If::append_then(const ValueRef &cond, const ValueRef &value) {
- assert(cond);
- assert(value);
- Clause clause;
- clause.cond = cond;
- clause.value = value;
- clauses.push_back(clause);
-}
-
-void If::append_else(const ValueRef &value) {
- assert(value);
- Clause clause;
- clause.value = value;
- clauses.push_back(clause);
+CondTemplateRef CondTemplate::from(
+ const ValueRef &cond, const ValueRef &then_value, const ValueRef &else_value) {
+ return ref(unknown_anchor(), new CondTemplate(cond, then_value, else_value));
}
//------------------------------------------------------------------------------
M src/value.hpp +6 -18
@@ 330,28 330,16 @@ struct CondBr : Instruction {
//------------------------------------------------------------------------------
-struct If : UntypedValue {
- struct Clause {
- ValueRef cond;
- ValueRef value;
-
- Clause() {}
-
- bool is_then() const;
- };
-
- typedef std::vector<Clause> Clauses;
-
+struct CondTemplate : UntypedValue {
static bool classof(const Value *T);
- If(const Clauses &clauses);
+ CondTemplate(const ValueRef &cond, const ValueRef &then_value, const ValueRef &else_value);
- static IfRef from(const Clauses &clauses = {});
+ static CondTemplateRef from(const ValueRef &cond, const ValueRef &then_value, const ValueRef &else_value);
- void append_then(const ValueRef &cond, const ValueRef &value);
- void append_else(const ValueRef &value);
-
- Clauses clauses;
+ ValueRef cond;
+ ValueRef then_value;
+ ValueRef else_value;
};
//------------------------------------------------------------------------------
M src/value_kind.hpp +1 -1
@@ 19,7 19,7 @@ namespace scopes {
T(VK_Quote, "value-kind-quote", Quote) \
T(VK_Unquote, "value-kind-unquote", Unquote) \
T(VK_CompileStage, "value-kind-compile-stage", CompileStage) \
- T(VK_If, "value-kind-if", If) \
+ T(VK_CondTemplate, "value-kind-cond-template", CondTemplate) \
T(VK_SwitchTemplate, "value-kind-switch-template", SwitchTemplate) \
T(VK_MergeTemplate, "value-kind-merge-template", MergeTemplate) \
T(VK_CallTemplate, "value-kind-call-template", CallTemplate) \
M testing/test_spirv_loop.sc +6 -3
@@ 5,10 5,13 @@ fn function-with-exception ()
raise;
10
+fn unconst (x) x
+
fn main ()
- #if true 1
- #elseif true 2
- #else 3
+ if true 1
+ elseif ((let k = (unconst 1)) == 1)
+ k
+ else 3
try
let count = (function-with-exception)
for i j in (zip (range count) (range 16))