blob: f7990d20a848be14d839940c36dc6e429e743d36 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2020 fortiss GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Martin Jobst
* - initial API and implementation and/or initial documentation
* Kirill Dorofeev - extended support for adapters used in BFB
*******************************************************************************/
package org.eclipse.fordiac.ide.export.forte_lua.filter
import java.util.ArrayList
import java.util.HashMap
import java.util.List
import java.util.Map
import org.eclipse.fordiac.ide.model.libraryElement.AdapterEvent
import org.eclipse.fordiac.ide.model.libraryElement.Algorithm
import org.eclipse.fordiac.ide.model.libraryElement.BasicFBType
import org.eclipse.fordiac.ide.model.libraryElement.ECC
import org.eclipse.fordiac.ide.model.libraryElement.ECState
import org.eclipse.fordiac.ide.model.libraryElement.ECTransition
import org.eclipse.fordiac.ide.model.libraryElement.STAlgorithm
import org.eclipse.fordiac.ide.model.libraryElement.VarDeclaration
import org.eclipse.xtend.lib.annotations.Accessors
import static extension org.eclipse.emf.ecore.util.EcoreUtil.getRootContainer
import static extension org.eclipse.fordiac.ide.export.forte_lua.filter.LuaConstants.*
import org.eclipse.fordiac.ide.model.libraryElement.AdapterDeclaration
class BasicFBFilter {
@Accessors(PUBLIC_GETTER)
private List<String> errors = new ArrayList<String>;
private STAlgorithmFilter stAlgorithmFilter = new STAlgorithmFilter
def lua(BasicFBType type) '''
«type.luaConstants»
«type.luaAlgorithms»
«type.ECC.luaStates»
«type.ECC.luaECC(type.variables, type.adapterSocketsVariables, type.adapterPlugsVariables)»
«type.interfaceList.luaInterfaceSpec»
«type.luaInternalVarsInformation»
return {ECC = executeEvent, interfaceSpec = interfaceSpec, internalVarsInformation = internalVarsInformation}
'''
def private luaECC(ECC ecc, Iterable<VarDeclaration> variables,
Map<AdapterDeclaration, String> adapterSocketsVariables,
Map<AdapterDeclaration, String> adapterPlugsVariables) '''
local function transition(fb, id)
local «luaStateVariable()» = «luaFBStateVariable()»
«variables.luaFBVariablesPrefix»
«FOR adapter : adapterSocketsVariables.keySet»
«FOR input: adapter.type.adapterFBType.interfaceList.inputVars»
«input.luaFBAdapterInECCVariablesPrefix(adapter.name, false)»
«ENDFOR»
«FOR output: adapter.type.adapterFBType.interfaceList.outputVars»
«output.luaFBAdapterInECCVariablesPrefix(adapter.name, false)»
«ENDFOR»
«ENDFOR»
«FOR adapter : adapterPlugsVariables.keySet»
«FOR input: adapter.type.adapterFBType.interfaceList.inputVars»
«input.luaFBAdapterInECCVariablesPrefix(adapter.name, true)»
«ENDFOR»
«FOR output: adapter.type.adapterFBType.interfaceList.outputVars»
«output.luaFBAdapterInECCVariablesPrefix(adapter.name, true)»
«ENDFOR»
«ENDFOR»
«ecc.luaTransitions»
end
local function executeEvent(fb, id)
local modified = transition(fb, id)
while modified do
modified = transition(fb, -1)
end
end
'''
def private Iterable<VarDeclaration> getVariables(BasicFBType type) {
type.interfaceList.inputVars + type.interfaceList.outputVars + type.internalVars
}
def private Map<AdapterDeclaration, String> getAdapterSocketsVariables(BasicFBType type) {
var Map<AdapterDeclaration, String> ret = new HashMap<AdapterDeclaration, String>;
for (adapterDecl : type.interfaceList.sockets) {
ret.put(adapterDecl, adapterDecl.name)
}
return ret
}
def private Map<AdapterDeclaration, String> getAdapterPlugsVariables(BasicFBType type) {
var Map<AdapterDeclaration, String> ret = new HashMap<AdapterDeclaration, String>;
for (adapterDecl : type.interfaceList.plugs) {
ret.put(adapterDecl, adapterDecl.name)
}
return ret
}
def private luaTransitions(ECC ecc) '''
«FOR state : ecc.ECState BEFORE 'if ' SEPARATOR '\nelseif ' AFTER '\nelse return false\nend
«state.luaStateName» == «luaStateVariable» then
«state.luaTransition»«ENDFOR»'''
def private luaTransition(ECState state) '''
«FOR tran : state.outTransitions BEFORE 'if ' SEPARATOR '\nelseif ' AFTER '\nelse return false\nend
«tran.luaTransitionCondition» then return enter«tran.destination.luaStateName»(fb)«ENDFOR»'''
def private luaTransitionCondition(
ECTransition tran) '''«IF tran.conditionEvent != null»«tran.conditionEvent.luaInputEventName» == id«ELSE»true«ENDIF» and «IF !tran.conditionExpression.nullOrEmpty»«tran.luaTransitionConditionExpression»«ELSE»true«ENDIF»'''
def private luaTransitionConditionExpression(ECTransition tran) {
val type = tran.rootContainer as BasicFBType
stAlgorithmFilter.lua(type, tran.conditionExpression)
}
def private luaStates(ECC ecc) '''
«FOR state : ecc.ECState»
«state.luaState»
«ENDFOR»
'''
def private luaState(ECState state) '''
local function enter«state.luaStateName»(fb)
«luaFBStateVariable» = «state.luaStateName»
«FOR action : state.ECAction»
«IF null != action.algorithm»«action.algorithm.luaAlgorithmName»(fb)«ENDIF»
«IF action.output instanceof AdapterEvent»
«action.output?.luaSendAdapterOutputEvent»
«ELSE»
«action.output?.luaSendOutputEvent»
«ENDIF»
«ENDFOR»
return true
end
'''
def private luaAlgorithms(BasicFBType type) '''
«FOR alg : type.algorithm»
«alg.luaAlgorithm»
«ENDFOR»
'''
def private dispatch luaAlgorithm(Algorithm alg) {
throw new UnsupportedOperationException("Cannot export algorithm " + alg.class)
}
def private dispatch luaAlgorithm(STAlgorithm alg) {
val result = '''
local function «alg.luaAlgorithmName»(fb)
«stAlgorithmFilter.lua(alg)»
end
'''
errors.addAll(stAlgorithmFilter.errors.map['''Error in algorithm «alg.name»: «it»'''])
stAlgorithmFilter.errors.clear()
return result
}
}