
%

%   Copyright 2012-2019 The MathWorks, Inc.

classdef (Sealed) PLCCGProcOmron < handle
    properties (Hidden, Access = private)
        fController
        fIsModified = false;
        fUseTrunc = false;
    end
    
    methods
        function obj = PLCCGProcOmron(controller)
            obj.fController = controller;
        end
        
        function doIt(obj)
            for i = 1 : length(obj.fController.components)
                code = obj.fController.components(i).body;
                code = obj.fixTrunc(code);
                code = obj.fixShift(code);
                obj.fController.components(i).body = code;
            end
            if obj.fUseTrunc
                obj.fController.components(end+1) = obj.genPLCTrunc;
            end
        end
        
        function flag = isModified(obj)
            flag = obj.fIsModified;
        end
        
        function setModified(obj)
            if ~obj.fIsModified
                obj.fIsModified = true;
            end
        end
        
        function controller = getController(obj)
            controller = obj.fController;
        end
        
        function code = fixTrunc(obj, code)
            if contains(code, 'TRUNC')
                obj.setModified;
                code = regexprep(code, 'TRUNC\(', 'PLC_TRUNC\(');
                if ~obj.fUseTrunc
                    obj.fUseTrunc = true; 
                end
            end
        end

        function code = fixShift(obj, code)
            opcode = '(SHL|SHR|ROL|ROR)';
            if ~isempty(regexp(code, opcode, 'once'))
                obj.setModified;
                pattern = [opcode '\(([\w|#]+),\s+([\w|#]+)\)']; 
                code = regexprep(code, pattern, '$1\($2, DINT_TO_USINT\($3\)\)');                
            end
        end

        function pou = genPLCTrunc(obj)
            pou = obj.genPOUComponent('PLC_TRUNC', [], ...
                false, ...
                {'u', 'LREAL', ''}, ...
                {'y', 'DINT', ''}, ...
                {}, ...
                {}, ...
                {}, ...
                {}, ...
                'PLC_TRUNC := LINT_TO_DINT(TRUNC(u));\n');    
        end

        function component = genPOUComponent(obj, name, desc, isFB, inputs, outputs, inouts, locals, temps, instances, body)
            component.name = name;
            component.desc = desc;
            if isFB
                component.type = 'FUNCTION_BLOCK';
            else
                component.type = 'FUNCTION';
            end
            component.externals = [];
            component.external_constants = []; %g1965949
            component.inputs = obj.genPOUVarList(inputs);
            component.outputs = obj.genPOUVarList(outputs);
            component.inouts = obj.genPOUVarList(inouts);
            component.locals = obj.genPOUVarList(locals);
            component.instances = obj.genPOUVarList(instances);
            component.temps = obj.genPOUVarList(temps);
            component.body = sprintf(body);
        end

        function result = genPOUVarList(obj, vars)
            result = [];
            for i = 1 : 3 : length(vars)
                result = [result obj.genPOUVar(vars{i}, vars{i + 1}, vars{i + 2})]; %#ok<AGROW>
            end
        end

        function var = genPOUVar(obj, name, type, value) %#ok<INUSL>
            var.name = name;
            var.type.kind = 'element';
            var.type.name = type;
            var.value = value;
        end        
    end
end

% LocalWords:  TRUNC SHL SHR ROL ROR USINT LREAL
