Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "OMParser"
uuid = "11f87224-cae7-4e99-a924-e50d12f62c59"
authors = ["Adrian Pop <adrian.pop@liu.se>", "John Tinnerholm <john.tinnerholm@liu.se>"]
version = "0.2.1"
version = "0.2.2"

[deps]
Absyn = "ce2f92e2-a952-11e9-0543-8b443f216f1d"
Expand All @@ -20,7 +20,7 @@ ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"

[compat]
julia = "1.13"
Absyn = "=1.3.5"
Absyn = "1.4"
ImmutableList = "0.4.2"
MetaModelica = "0.4.2"

Expand Down
20 changes: 15 additions & 5 deletions lib/parser/GenerateJLHeader.jl
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ function programExternalHeaderJulia(allDataTypes, moduleName)
local jlValues::String = generateJL_Values(allDataTypes)
#= Generate all JL values=#
println(buffer, jlValues)
println(buffer, "jl_value_t *OMParser_missingAbsyn(const char *name) {")
println(buffer, " jl_errorf(\"The loaded Absyn package has no Absyn.%s, which this OMParser library builds: update Absyn.\", name);")
println(buffer, " return NULL;")
println(buffer, "}")
println(buffer, "void OpenModelica_initAbsynReferences() {")
#= Get the code in the body of initAbsynReferences =#
local jlAsserts = generateJL_Asserts(allDataTypes, moduleName)
Expand Down Expand Up @@ -278,10 +282,13 @@ function generateJL_Asserts(allDataTypes, moduleName)
local qualifiedName = getSuperTypePath(dataType)
#= Get qualified path for basic datatype =#
local baseTypeStr = components[2]
local assertStr1 = "assert(($qualifiedName = jl_get_function($(moduleName), \"$(baseTypeStr)\")));"
local assertStr2 = "assert(($(qualifiedName)_type = jl_get_global($(moduleName), jl_symbol(\"$(baseTypeStr)\"))));"
println(buffer, assertStr1)
println(buffer, assertStr2)
#= Not asserted: a record the loaded Absyn lacks (an older Absyn than the grammar's) stays
NULL, and only the syntax that builds it fails (OMParser_missingAbsyn), so a library built
from a newer grammar still works with an older Absyn. =#
local assignStr1 = "$qualifiedName = jl_get_function($(moduleName), \"$(baseTypeStr)\");"
local assignStr2 = "$(qualifiedName)_type = jl_get_global($(moduleName), jl_symbol(\"$(baseTypeStr)\"));"
println(buffer, assignStr1)
println(buffer, assignStr2)
#=TODO is the double underscore important?=#
end
end
Expand All @@ -300,6 +307,7 @@ This is followed by a function definition
function generateExternalDeclarations(allSuperTypes)
local buffer = IOBuffer()
println(buffer, "/* Extern declarations */")
println(buffer, "jl_value_t *OMParser_missingAbsyn(const char *name);")
for superType in allSuperTypes
local subTypes = subtypes(superType)
local components = split(string(superType), ".")
Expand All @@ -325,7 +333,7 @@ function generateExternalDeclarations(allSuperTypes)
local fieldNameLength = length(fieldNames)
local fullName = string("Absyn__", replace(getBaseNameAsStr(subType), "_" => "_5f"))
if fieldNameLength == 0
println(buffer, "#define $(fullName) jl_call0($(qualifiedName))")
println(buffer, "#define $(fullName) ($(qualifiedName) ? jl_call0($(qualifiedName)) : OMParser_missingAbsyn(\"$(baseTypeStr)\"))")
elseif fieldNameLength <= 3
local fieldNamesAsStrWithType = join(map((x) -> string("jl_value_t *", x), fieldNames), ", ")
local fieldNamesAsStrWithoutType = join(map(string, fieldNames), ", ")
Expand All @@ -334,6 +342,7 @@ function generateExternalDeclarations(allSuperTypes)
local body = string("return ","jl_call", string(fieldNameLength), "(", qualifiedName, ", " ,fieldNamesAsStrWithoutType, ")", ";")
local staticFuncEpilog = "}"
println(buffer, staticFuncHeader)
println(buffer, "if (!$(qualifiedName)) return OMParser_missingAbsyn(\"$(baseTypeStr)\");")
println(buffer, body)
println(buffer, staticFuncEpilog)
else
Expand All @@ -345,6 +354,7 @@ function generateExternalDeclarations(allSuperTypes)
local returnStmt = string("return ","jl_call", "(", qualifiedName, ", " ,"values, ", "$(fieldNameLength)" ,")", ";")
local staticFuncEpilog = "}"
println(buffer, staticFuncHeader)
println(buffer, "if (!$(qualifiedName)) return OMParser_missingAbsyn(\"$(baseTypeStr)\");")
println(buffer, arrayDecl)
println(buffer, returnStmt)
println(buffer, staticFuncEpilog)
Expand Down
61 changes: 45 additions & 16 deletions lib/parser/Modelica.g
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ implicit_import_name returns [void* ast]
// allowing the comment.
extends_clause returns [void* ast]
@init { OM_PUSHZ3(path, mod, ann); } :
EXTENDS path=name_path (mod=class_modification)? (ann=annotation)?
EXTENDS path=name_path (mod=class_or_inheritance_modification)? (ann=annotation)?
{
ast = Absyn__EXTENDS(path,or_nil(mod),mmc_mk_some_or_none(ann));
}
Expand Down Expand Up @@ -741,37 +741,66 @@ declaration returns [void* ast]
*/

modification returns [void* ast]
@init { OM_PUSHZ2(e.ast, cm); eq = 0; } :
( cm=class_modification ( eq=EQUALS e=expression[metamodelica_enabled()] )?
| eq=EQUALS e=expression[metamodelica_enabled()]
| eq=ASSIGN e=expression[metamodelica_enabled()] {c_add_source_message(NULL,2, ErrorType_syntax, ErrorLevel_warning, ":= in modifiers has been deprecated",
@init { OM_PUSHZ2(e, cm); eq = 0; } :
( cm=class_modification ( eq=EQUALS e=modification_expression )?
| eq=EQUALS e=modification_expression
| eq=ASSIGN e=modification_expression {c_add_source_message(NULL,2, ErrorType_syntax, ErrorLevel_warning, ":= in modifiers has been deprecated",
NULL, 0, $start->line, $start->charPosition+1, LT(1)->line, LT(1)->charPosition+1,
ModelicaParser_readonly, ModelicaParser_filename_C_testsuiteFriendly);}
)
{
$ast = Absyn__CLASSMOD(or_nil(cm), e.ast ? Absyn__EQMOD(e.ast,PARSER_INFO($eq)) : Absyn__NOMOD);
$ast = Absyn__CLASSMOD(or_nil(cm), e ? Absyn__EQMOD(e,PARSER_INFO($eq)) : Absyn__NOMOD);
}
;
finally{ OM_POP(2); }

/* A modifier's value, or `break` to remove the binding (Modelica 3.6). */
modification_expression returns [void* ast]
@init { OM_PUSHZ1(e.ast); } :
e=expression[metamodelica_enabled()] { ast = e.ast; }
| BREAK { ast = Absyn__BREAK; }
;
finally{ OM_POP(1); }

class_modification returns [void* ast]
@init { OM_PUSHZ2(as, ast); } :
LPAR ( as=argument_list )? RPAR { ast = or_nil(as); }
LPAR ( as=argument_list[0] )? RPAR { ast = or_nil(as); }
;
finally{ OM_POP(2); }

argument_list returns [void* ast]
@init { OM_PUSHZ3(a, as, ast); } :
a=argument ( COMMA as=argument_list )?
/* The modification of an extends clause, which may also break inherited elements (Modelica 3.6
selective model extension). */
class_or_inheritance_modification returns [void* ast]
@init { OM_PUSHZ2(as, ast); } :
LPAR ( as=argument_list[1] )? RPAR { ast = or_nil(as); }
;
finally{ OM_POP(2); }

argument_list [int canHaveBreak] returns [void* ast]
@init { OM_PUSHZ4(a, b.ast, as, ast); } :
(a=argument | {canHaveBreak == 1}? b=inheritance_modification) ( COMMA as=argument_list[canHaveBreak] )?
{
if (!a)
{
fprintf(stderr, "crap!\n");
}
ast = mmc_mk_cons_typed(Absyn_ElementArg, a, or_nil(as));
ast = mmc_mk_cons_typed(Absyn_ElementArg, a ? a : b.ast, or_nil(as));
}
;
finally{ OM_POP(3); }
finally{ OM_POP(4); }

/* `break x` (stored as connect(break, x), as omc) or `break connect(a, b)`. */
inheritance_modification returns [void* ast]
@init { i = 0; OM_PUSHZ1(c); } :
BREAK ( c=connect_clause { $ast = Absyn__INHERITANCEBREAK(c, PARSER_INFO($start)); }
| i=IDENT
{
$ast = Absyn__INHERITANCEBREAK(
Absyn__EQ_5fCONNECT(
Absyn__CREF_5fIDENT(mmc_mk_scon("break"),mmc_mk_nil()),
Absyn__CREF_5fIDENT(token_to_scon(i),mmc_mk_nil())
),
PARSER_INFO($start));
}
)
;
finally{ OM_POP(1); }

argument returns [void* ast]
@init { OM_PUSHZ2(em, er.ast); } :
Expand Down
23 changes: 23 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,29 @@ cd(@__DIR__) do
include("metaModelicaTests.jl")

#= Warning might be flaky... =#
#= Modelica 3.6 selective model extension. =#
@testset "Break modifiers" begin
local p = OMParser.parseString("""
model B
extends A(break x, break connect(a.p, b.n), y = 2);
Real z(start = break) = break;
end B;
""")
local parts = p.classes.head.body.classParts.head.contents
local ext = parts.head.element.specification
local args = collect(ext.elementArg)
@test length(args) == 3
@test args[1] isa OMParser.Absyn.INHERITANCEBREAK
@test args[1].cnct.connector1.name == "break" && args[1].cnct.connector2.name == "x"
@test args[2] isa OMParser.Absyn.INHERITANCEBREAK
@test args[2].cnct.connector1 isa OMParser.Absyn.CREF_QUAL
@test args[3] isa OMParser.Absyn.MODIFICATION
local comp = parts.tail.head.element.specification.components.head.component
@test comp.modification.data.eqMod.exp isa OMParser.Absyn.BREAK
#= Only extends clauses may break elements. =#
@test_throws Exception OMParser.parseString("model M A a(break x); end M;")
end

@testset "Standard Library" begin
@test true == begin
try
Expand Down
Loading