Template semantics - #1006
Conversation
…mbols for nested template expansion
…-semantics and fix it up
7528e98 to
5fdf152
Compare
|
@bocchino I've dug into the Test caseError DiagnosisThe error: The answer was actually encoded exactly in this error message though the message itself was misleading. See this snippet below: fpp/compiler/lib/src/main/scala/analysis/Semantics/Type.scala Lines 347 to 350 in cc7fec0 When an anonymous array size is known, the name of the array is fpp/compiler/lib/src/main/scala/analysis/Semantics/Value.scala Lines 65 to 70 in cc7fec0
CauseAs an initial note, the Let's read the FPP spec on commonType:
I believe the issue is with step 6. We are stripping away the concrete array type for an anonymous array with unknown size. This was ok before because there was never a case where this case was hit. There was never a case in which a value of concrete array type could be constructed and that value be As a side note: I think anonymous arrays of None size should never be possible at any point in the analysis. Anonymous arrays stem from array literals which should always be trivially determined since you can just count the number of elements in the syntax. It may be worth keeping this in the semantics as a mechanism to allow concrete Arrays to wrap AnonArray which would allow None sizes. A side-note to my side note: Anonymous arrays of FixWe need to change the semantics of // (Array, Array) case
// (Array, AnonArray)
// (Array, promotableToArray(T))
... continue onward with the same rules Implementation note!
I'm mainly referring to Step 7a where we check |
I think it's trying to apply step 8 (common type of Integer and [n] U32) at a point where n is unknown. I don't think we need to revise the spec. I think we need to revise the implementation. One way to do it is to accumulate constraints at the point of type checking where the sizes aren't known, and check the constraints later after we know the sizes. |
I think the spec is correct here. For example, if A and B are both array types with shape [2] U32, then the common type should be the shape (anonymous array). The common type should be the least type to which both types are assignable. |
Actually I suspect what may be happening is this:
So a solution may be to relax the value conversion rules to allow the temporary formation of array values with unknown sizes, analogously to how we temporarily form array types with unknown sizes. That should provide enough scalar value info to finalize the array values and the array types. |
Disallow template composition
| expr.data match { | ||
| case Ast.ExprIdent(e) => Right(List(AstNode.create(e, expr.id))) | ||
| case Ast.ExprDot(e, id) => for (left <- exprToIdentList(e)) yield left :+ id | ||
| // TODO(tumbar) Make error messages specific to the parameter type |
| nestedScope <- nestedScope.put(NameGroup.Value)(param.getUnqualifiedName, param) | ||
| nestedScope <- nestedScope.put(NameGroup.Type)(param.getUnqualifiedName, param) | ||
| nestedScope <- nestedScope.put(NameGroup.PortInterfaceInstance)(param.getUnqualifiedName, param) |
There was a problem hiding this comment.
Don't add to all name-groups
| val eltType = a.typeMap(node.id) match { | ||
| case Type.AnonArray(_, eltType) => eltType | ||
| case Type.Array(_, Type.AnonArray(_, eltType), _, _) => eltType | ||
| case _ => throw InternalError("element type of array expression should be AnonArray") |
| override def toString = size match { | ||
| case Some(n) => "[" ++ n.toString ++ "] " ++ eltType.toString | ||
| case None => "array of " ++ eltType.toString | ||
| case None => "[unknown] " ++ eltType.toString |
| includingLoc: Option[Location] = None /* Location where this location is included */ | ||
| /* Location where this location is included */ | ||
| includeLoc: Option[Location] = None, | ||
| /* Location where this location is included */ |
| pos: Position, /* The position */ | ||
| includingLoc: Option[Location] = None /* Location where this location is included */ | ||
| /* Location where this location is included */ | ||
| includeLoc: Option[Location] = None, |
There was a problem hiding this comment.
Make into includingLoc and expandingLoc
| // Enum symbol: if this is in scope, then we are in | ||
| // the enum definition, so it already has a type | ||
| case Symbol.EnumConstant(node) => Right(a) | ||
| // Template parameter symbol: we are already inside the template expansion |
There was a problem hiding this comment.
| // Template parameter symbol: we are already inside the template expansion | |
| // Template constant argument symbol: we are already inside the template expansion |
| val scope = expansion.scope | ||
|
|
||
| // We do use-analysis on the scope of the definition + param scope | ||
| // This is a bit unorthadox but we need to build a new nested scope from scratch |
There was a problem hiding this comment.
| // This is a bit unorthadox but we need to build a new nested scope from scratch | |
| // This is a bit unorthodox but we need to build a new nested scope from scratch |
| } | ||
| } | ||
|
|
||
| // FIXME(tumbar) This is probably not needed |
There was a problem hiding this comment.
Let's fix this in this PR or open an issue to track it.
| defNode: Ast.Annotated[AstNode[Ast.DefModuleTemplate]], | ||
| /** The AST node expanding the template */ | ||
| expansion: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]], | ||
| /** Concrete parameters given to this template during expansion */ |
There was a problem hiding this comment.
| /** Concrete parameters given to this template during expansion */ | |
| /** Arguments bound to the parameters of this template during expansion */ |
| expansion: Ast.Annotated[AstNode[Ast.SpecTemplateExpand]], | ||
| /** Concrete parameters given to this template during expansion */ | ||
| params: Map[String, TemplateArgSymbol], | ||
| /** Scope where parameter symbols are entered */ |
There was a problem hiding this comment.
| /** Scope where parameter symbols are entered */ | |
| /** Scope where template argument symbols are entered */ |
| expr.data match { | ||
| case Ast.ExprIdent(e) => Right(List(AstNode.create(e, expr.id))) | ||
| case Ast.ExprDot(e, id) => for (left <- exprToIdentList(e)) yield left :+ id | ||
| // TODO(tumbar) Make error messages specific to the parameter type |
There was a problem hiding this comment.
Let's fix this TODO here or open an issue to track it.
| QualIdent.NodeList.split(nodeList) match { | ||
| case (Nil, name) => QualIdent.Unqualified(name.data) | ||
| case (qualifier, name) => { | ||
| // TODO(tumbar) Don't duplicate node ids |
There was a problem hiding this comment.
Let's fix this TODO here or open an issue to track it.

This PR includes the implementation of templates. I'm opening this PR so it's easier to track work and look at diffs, it is not ready for review/merge yet.