Skip to content

Commit

Permalink
Merge pull request #420 from icyphy/width-given-by-code
Browse files Browse the repository at this point in the history
Allow width to be specified in target code
  • Loading branch information
cmnrd authored Jul 27, 2021
2 parents e49cb5c + 39d161f commit ae6d573
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
3 changes: 2 additions & 1 deletion org.lflang/src/org/lflang/LinguaFranca.xtext
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ WidthSpec:
WidthTerm:
width=INT
| parameter=[Parameter]
| 'widthof(' port=VarRef ')';
| 'widthof(' port=VarRef ')'
| code=Code;

IPV4Host:
(user=Kebab '@')? addr=IPV4Addr (':' port=INT)?
Expand Down
9 changes: 5 additions & 4 deletions org.lflang/src/org/lflang/generator/cpp/CppExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ fun Time.toCode() = TimeValue(this.interval.toLong(), this.unit).toCode()
* This should be set to false if called from code generators for the inner class.
*/
fun Value.toTime(outerContext: Boolean = false): String = when {
this.time != null -> this.time.toCode()
this.isZero -> TimeValue(0, TimeUnit.NONE).toCode()
this.time != null -> this.time.toCode()
this.isZero -> TimeValue(0, TimeUnit.NONE).toCode()
outerContext && this.parameter != null -> "__lf_inner.${parameter.name}"
else -> this.toText()
else -> this.toText()
}

/**
Expand All @@ -109,7 +109,7 @@ fun Value.toTime(outerContext: Boolean = false): String = when {
fun Value.toCode(): String = this.time?.toCode() ?: this.toText()

/** Get the textual representation of a width in C++ code */
fun WidthSpec.toCode(): String = terms.joinToString(" + ") {
fun WidthSpec.toCode(): String = terms.joinToString(" + ") {
when {
it.parameter != null -> it.parameter.name
it.port != null -> with(it.port) {
Expand All @@ -121,6 +121,7 @@ fun WidthSpec.toCode(): String = terms.joinToString(" + ") {
else "1"
}
}
it.code != null -> it.code.toText()
else -> it.width.toString()
}
}
Expand Down
4 changes: 4 additions & 0 deletions org.lflang/src/org/lflang/validation/LFValidatorImpl.xtend
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ class LFValidatorImpl extends AbstractLFValidator {
// Widths given with `widthof()` are not supported (yet?).
// This feature is currently only used for after delays.
error("widthof is not supported.", Literals.WIDTH_SPEC__TERMS)
} else if (term.code !== null) {
if (this.target != Target.CPP) {
error("This target does not support width given as code.", Literals.WIDTH_SPEC__TERMS)
}
} else if (term.width < 0) {
error("Width must be a positive integer.", Literals.WIDTH_SPEC__TERMS)
}
Expand Down
37 changes: 37 additions & 0 deletions test/Cpp/src/multiport/WidthGivenByCode.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
target Cpp

reactor Foo(a: size_t{8}, b: size_t{2}) {
input[{=a*b=}] in: size_t;
output[{=a/b=}] out: size_t;

reaction (startup) in -> out {=
if (in.size() != a*b){
std::cerr << "ERROR: expected in to have a width of " << a*b << '\n';
exit(1);
}
if (out.size() != a/b){
std::cerr << "ERROR: expected out to have a width of " << a/b << '\n';
exit(2);
}
=}
}

main reactor {
foo1 = new Foo();
foo2 = new Foo(a=10, b=3);
foo3 = new Foo(a=9, b=9);
foo_bank = new[{=42=}] Foo();

reaction (startup) foo_bank.out {=
if (foo_bank.size() != 42) {
std::cerr << "ERROR: expected foo_bank to have a width of " << 42 << '\n';
exit(3);
}
for (auto& foo : foo_bank) {
if (foo.out.size() != 4) {
std::cerr << "ERROR: expected foo_bank.out to have a width of " << 4 << '\n';
exit(4);
}
}
=}
}

0 comments on commit ae6d573

Please sign in to comment.