上位机已经有丰富的编程语言,所以不再需要完整的PLC功能。提供梯形图的指令是用于快速配置的。
以下是文本解释型虚拟PLC。
package pers.laserpen.util.automation.plcEmulator;
import java.io.File;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.*;
import pers.laserpen.util.awt.Tip;
import pers.laserpen.util.data.StaticDataUtils;
import pers.laserpen.util.file.FreeFileIO;
import pers.laserpen.util.java.StaticJavaUtils;
import pers.laserpen.util.math.calculator.standardCalculator.DoubleLineCalculator;
import pers.laserpen.util.math.calculator.standardCalculator.StackPriorityCalculator;
import pers.laserpen.util.math.calculator.standardCalculator.StandardCalculator;
import pers.laserpen.util.thread.AccuracyTimer;
import pers.laserpen.util.math.calculator.standardCalculator.DoubleLineCalculator.Analysor;
import pers.laserpen.util.string.RegexBuilder;
import pers.laserpen.util.string.StaticStringUtils;
public class MitsubishiPLCEmulator {
private static final String SEPARATOR_IN_LINE = ((Supplier<String>) () -> {
RegexBuilder regex = new RegexBuilder();
regex.appendCharGroup(" \"\t,,\' \ufeff\0\f", false);
return regex.toString();
}).get();
private static final BinaryOperator<Object> END = (u, t) -> u;
private static final BinaryOperator<Object> CJ = (u, t) -> u;
private static final BinaryOperator<Object> JMP = (u, t) -> u;
private static final BinaryOperator<Object> CALL = (u, t) -> u;
private static final BinaryOperator<Object> RET = (u, t) -> u;
private Map<Integer, Integer> m_skipWhiteSpace = new HashMap<>();
private Map<Integer, BinaryOperator<Object>> m_quickOperators = new HashMap<>();
private Map<Integer, String> m_quickArgs = new HashMap<>();
private Map<Integer, Integer> m_P = new HashMap<>();
private Deque<Integer> m_retP = new ArrayDeque<>();
private Deque<Object> m_retV = new ArrayDeque<>();
private Map<Integer, Number> m_D = new HashMap<>();
private FreeFileIO m_savedD = null;
private int m_savedDOffset = 0;
private Map<Integer, DigitalPackage> m_M = new HashMap<>();
private FreeFileIO m_L = null;
private Map<Integer, DigitalPackage> m_SM = new HashMap<>();
private Map<Integer, DigitalPackage> m_mepOrMef = new HashMap<>();
private Map<Integer, DigitalPackage> m_CC = new HashMap<>();
private Map<Integer, Long> m_CN = new HashMap<>();
private Map<Integer, Long> m_CLIMIT = new ConcurrentHashMap<>();
private Map<Integer, DigitalPackage> m_CS = new HashMap<>();
private Map<Integer, DigitalPackage> m_TC = new ConcurrentHashMap<>();
private Map<Integer, Long> m_TN = new ConcurrentHashMap<>();
private Map<Integer, Long> m_TLIMIT = new ConcurrentHashMap<>();
private Map<Integer, DigitalPackage> m_TS = new ConcurrentHashMap<>();
private AccuracyTimer m_timer = new AccuracyTimer();
private Deque<Object> m_blockLogicStack = new ArrayDeque<>();
private Deque<Object> m_mpsCommandStack = new ArrayDeque<>();
private StackPriorityCalculator<Object> m_stackCalc = new StackPriorityCalculator<>(null);
private List<Analysor<Object>> m_analysors = new ArrayList<>();
private DoubleLineCalculator<Object> m_calc = new DoubleLineCalculator<>(m_stackCalc, m_analysors);
private int m_lineNumber = 0;
protected boolean m_operatorSetted = false;
public MitsubishiPLCEmulator(long tickTime) {
if (tickTime <= 0) {
StaticJavaUtils.exit("不支持负的延时");
}
m_timer.setTask(ct -> {
boolean doSth = false;
for (Entry<Integer, DigitalPackage> entry : m_TC.entrySet()) {
long tn = getTN(entry.getKey());
long tlim = getTLim(entry.getKey());
if (tn >= tlim) {
continue;
}
setTN(entry.getKey(), tn + 1);
doSth = true;
}
if (doSth) {
return tickTime;
} else {
return 0;
}
});
setSM(400, true);
setSM(401, false);
setM(8000, true);
setM(8001, false);
addOperators();
}
private void addOperators() {
addOperator("LDP", (last, key) -> {
if (last != null) {
m_blockLogicStack.push(last);
}
return toDigitalP(key);
});
addOperator("LDPI", (last, key) -> {
if (last != null) {
m_blockLogicStack.push(last);
}
return toDigitalPI(key);
});
addOperator("LDF", (last, key) -> {
if (last != null) {
m_blockLogicStack.push(last);
}
return toDigitalF(key);
});
addOperator("LDFI", (last, key) -> {
if (last != null) {
m_blockLogicStack.push(last);
}
return toDigitalFI(key);
});
addOperator("LDI", (last, key) -> {
if (last != null) {
m_blockLogicStack.push(last);
}
return toDigitalI(key);
});
addOperator("LD", (last, key) -> {
if (last != null) {
m_blockLogicStack.push(last);
}
return toDigital(key);
});
addOperator("LD>", (a, b) -> {
if (a != null) {
m_blockLogicStack.push(a);
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
return n1.doubleValue() > n2.doubleValue();
});
addOperator("LD>=", (a, b) -> {
if (a != null) {
m_blockLogicStack.push(a);
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
return n1.doubleValue() >= n2.doubleValue();
});
addOperator("LD<", (a, b) -> {
if (a != null) {
m_blockLogicStack.push(a);
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
return n1.doubleValue() < n2.doubleValue();
});
addOperator("LD<=", (a, b) -> {
if (a != null) {
m_blockLogicStack.push(a);
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
return n1.doubleValue() <= n2.doubleValue();
});
addOperator("LD<>", (a, b) -> {
if (a != null) {
m_blockLogicStack.push(a);
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
return n1.doubleValue() != n2.doubleValue();
});
addOperator("LD=", (a, b) -> {
if (a != null) {
m_blockLogicStack.push(a);
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
return n1.doubleValue() == n2.doubleValue();
});
addOperator("OUT", (a, b) -> {
m_blockLogicStack.clear();
String to = b.toString();
to = to.toUpperCase();
String[] args = to.split(SEPARATOR_IN_LINE);
int index = Integer.parseInt(args[0].substring(1));
if (to.startsWith("M")) {
setM(index, (Boolean) a);
} else if (to.startsWith("T")) {
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
setTLim(index, toNumber(args[1]).intValue());
setTC(index, (Boolean) a);
} else if (to.startsWith("C")) {
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
setCLim(index, toNumber(args[1]).intValue());
setCC(index, (Boolean) a);
} else if (to.startsWith("L")) {
setL(index, (Boolean) a);
}
return a;
});
addOperator("AND", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigital(b);
return b1 && b2;
});
addOperator("ANI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalI(b);
return b1 && b2;
});
addOperator("ANDP", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalP(b);
return b1 && b2;
});
addOperator("ANDPI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalPI(b);
return b1 && b2;
});
addOperator("ANDF", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalF(b);
return b1 && b2;
});
addOperator("ANDFI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalFI(b);
return b1 && b2;
});
addOperator("AND<", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (!b1) {
return false;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() < n2.doubleValue();
return b1 && b2;
});
addOperator("AND<=", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (!b1) {
return false;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() <= n2.doubleValue();
return b1 && b2;
});
addOperator("AND>", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (!b1) {
return false;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() > n2.doubleValue();
return b1 && b2;
});
addOperator("AND>=", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (!b1) {
return false;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() >= n2.doubleValue();
return b1 && b2;
});
addOperator("AND<>", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (!b1) {
return false;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() != n2.doubleValue();
return b1 && b2;
});
addOperator("AND=", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (!b1) {
return false;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() == n2.doubleValue();
return b1 && b2;
});
addOperator("OR", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigital(b);
return b1 || b2;
});
addOperator("ORI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalI(b);
return b1 || b2;
});
addOperator("ORP", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalP(b);
return b1 || b2;
});
addOperator("ORPI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalPI(b);
return b1 || b2;
});
addOperator("ORF", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalF(b);
return b1 || b2;
});
addOperator("ORFI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalFI(b);
return b1 || b2;
});
addOperator("OR<", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (b1) {
return true;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() < n2.doubleValue();
return b1 || b2;
});
addOperator("OR<=", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (b1) {
return true;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() <= n2.doubleValue();
return b1 || b2;
});
addOperator("OR>", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (b1) {
return true;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() > n2.doubleValue();
return b1 || b2;
});
addOperator("OR>=", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (b1) {
return true;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() >= n2.doubleValue();
return b1 || b2;
});
addOperator("OR<>", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (b1) {
return true;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() != n2.doubleValue();
return b1 || b2;
});
addOperator("OR=", (a, b) -> {
boolean b1 = toDigital(a), b2;
if (b1) {
return true;
}
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() == n2.doubleValue();
return b1 || b2;
});
addOperator("XOR", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigital(b);
return b1 != b2;
});
addOperator("XORI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalI(b);
return b1 != b2;
});
addOperator("XORP", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalP(b);
return b1 != b2;
});
addOperator("XORPI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalPI(b);
return b1 != b2;
});
addOperator("XORF", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalF(b);
return b1 != b2;
});
addOperator("XORFI", (a, b) -> {
boolean b1 = toDigital(a), b2 = toDigitalFI(b);
return b1 != b2;
});
addOperator("XOR<", (a, b) -> {
boolean b1 = toDigital(a), b2;
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() < n2.doubleValue();
return b1 != b2;
});
addOperator("XOR<=", (a, b) -> {
boolean b1 = toDigital(a), b2;
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() <= n2.doubleValue();
return b1 != b2;
});
addOperator("XOR>", (a, b) -> {
boolean b1 = toDigital(a), b2;
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() > n2.doubleValue();
return b1 != b2;
});
addOperator("XOR>=", (a, b) -> {
boolean b1 = toDigital(a), b2;
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() >= n2.doubleValue();
return b1 != b2;
});
addOperator("XOR<>", (a, b) -> {
boolean b1 = toDigital(a), b2;
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() != n2.doubleValue();
return b1 != b2;
});
addOperator("XOR=", (a, b) -> {
boolean b1 = toDigital(a), b2;
String[] args = b.toString().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number n1 = toNumber(args[0]);
Number n2 = toNumber(args[1]);
b2 = n1.doubleValue() == n2.doubleValue();
return b1 != b2;
});
addOperator("ANB", (a, b) -> {
boolean b1 = toDigital(a), b2 = (boolean) m_blockLogicStack.pop();
return b1 && b2;
});
addOperator("ORB", (a, b) -> {
boolean b1 = toDigital(a), b2 = (boolean) m_blockLogicStack.pop();
return b1 || b2;
});
addOperator("XORB", (a, b) -> {
boolean b1 = toDigital(a), b2 = (boolean) m_blockLogicStack.pop();
return b1 != b2;
});
addOperator("MPS", (a, b) -> {
m_mpsCommandStack.push(a);
return a;
});
addOperator("MPP", (a, b) -> {
return m_mpsCommandStack.pop();
});
addOperator("MPD", (a, b) -> {
return m_mpsCommandStack.peek();
});
addOperator("INV", (a, b) -> {
return !(boolean) a;
});
addOperator("SET", (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String to = b.toString();
to = to.toUpperCase();
int index = Integer.parseInt(to.substring(1));
if (to.startsWith("M")) {
setM(index, true);
} else if (to.startsWith("L")) {
setL(index, true);
}
}
return a;
});
addOperator("RST", (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String to = b.toString();
to = to.toUpperCase();
int index = Integer.parseInt(to.substring(1));
if (to.startsWith("M")) {
setM(index, false);
} else if (to.startsWith("L")) {
setL(index, false);
} else {
setNumber(to, 0, 0);
}
}
return a;
});
addOperator("MOV", (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number value = toNumber(args[0]);
setNumber(args[1], 0, value);
}
return a;
});
addOperator("WAND", (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
if (args.length < 3) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number addition1 = toNumber(args[0]);
Number addition2 = toNumber(args[1]);
Number ans = addition1.longValue() & addition2.longValue();
setNumber(args[2], 0, ans);
}
return a;
});
addOperator("WOR", (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
if (args.length < 3) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number addition1 = toNumber(args[0]);
Number addition2 = toNumber(args[1]);
Number ans = addition1.longValue() | addition2.longValue();
setNumber(args[2], 0, ans);
}
return a;
});
addOperator("WXOR", (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
if (args.length < 3) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number addition1 = toNumber(args[0]);
Number addition2 = toNumber(args[1]);
Number ans = addition1.longValue() ^ addition2.longValue();
setNumber(args[2], 0, ans);
}
return a;
});
addOperator("CML", (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
if (args.length < 2) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number addition1 = toNumber(args[0]);
Number ans = ~addition1.longValue();
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("NEG", (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
if (args.length < 1) {
Tip.defaultTip("参数数量错误,检查操作数的数量(" + m_lineNumber + ")");
}
Number num = toNumber(args[0]);
setNumber(args[0], 0, -num.doubleValue());
}
return a;
});
BinaryOperator<Object> ADD = (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
Number addition1 = toNumber(args[0]);
Number addition2 = toNumber(args[1]);
Number ans = addition1.doubleValue() + addition2.doubleValue();
setNumber(args.length == 2 ? args[1] : args[2], 0, ans);
}
return a;
};
addOperator("ADD", ADD);
addOperator("+", ADD);
BinaryOperator<Object> SUB = (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
if (args.length == 3) {
Number addition1 = toNumber(args[0]);
Number addition2 = toNumber(args[1]);
Number ans = addition1.doubleValue() - addition2.doubleValue();
setNumber(args[2], 0, ans);
} else if (args.length == 2) {
Number addition1 = toNumber(args[1]);
Number addition2 = toNumber(args[0]);
Number ans = addition1.doubleValue() - addition2.doubleValue();
setNumber(args[1], 0, ans);
}
}
return a;
};
addOperator("SUB", SUB);
addOperator("-", SUB);
BinaryOperator<Object> MUL = (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
Number addition1 = toNumber(args[0]);
Number addition2 = toNumber(args[1]);
Number ans = addition1.doubleValue() * addition2.doubleValue();
setNumber(args.length == 2 ? args[1] : args[2], 0, ans);
}
return a;
};
addOperator("MUL", MUL);
addOperator("*", MUL);
BinaryOperator<Object> DIV = (a, b) -> {
m_blockLogicStack.clear();
if (toDigital(a)) {
String[] args = b.toString().toUpperCase().split(SEPARATOR_IN_LINE);
if (args.length == 3) {
Number addition1 = toNumber(args[0]);
Number addition2 = toNumber(args[1]);
Number ans = addition1.doubleValue() / addition2.doubleValue();
Number ans1 = addition1.doubleValue() % addition2.doubleValue();
setNumber(args[2], 0, ans);
setNumber(args[2], 1, ans1);
} else if (args.length == 2) {
Number addition1 = toNumber(args[1]);
Number addition2 = toNumber(args[0]);
Number ans = addition1.doubleValue() / addition2.doubleValue();
Number ans1 = addition1.doubleValue() % addition2.doubleValue();
setNumber(args[1], 0, ans);
setNumber(args[1], 1, ans1);
}
}
return a;
};
addOperator("DIV", DIV);
addOperator("/", DIV);
addOperator("SIN", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.sin(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("COS", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.cos(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("TAN", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.tan(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("ASIN", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.asin(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("ACOS", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.acos(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("ATAN", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.atan(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("EXP", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.exp(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("LOG", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.log(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("LOG10", (a, b) -> {
if (toDigital(a)) {
String[] args = b.toString().split(SEPARATOR_IN_LINE);
Number x = toNumber(args[0]);
double ans = Math.log10(x.doubleValue());
setNumber(args[1], 0, ans);
}
return a;
});
addOperator("P", (a, b) -> {
return a;
});
addJUMP("CJ", CJ, true, false);
addJUMP("JMP", JMP, false, false);
addJUMP("CALL", CALL, true, true);
addRET();
addEnd();
addMep();
addMef();
addQuickOperator();
Collections.sort(m_analysors, (a, b) -> {
String s1 = a.toString();
String s2 = b.toString();
int comp = s2.length() - s1.length();
if (comp != 0) {
return comp;
}
return s2.compareTo(s1);
});
addOperationNum();
System.out.println(m_analysors);
}
private void addQuickOperator() {
Analysor<Object> analysor = new Analysor<Object>() {
@Override
public String toString() {
return "QUICK OPERATOR";
}
@Override
public int analyse(StandardCalculator<Object> calculator, String command, int offset) {
BinaryOperator<Object> quickOper = m_quickOperators.get(offset);
if (quickOper == null) {
return SKIP;
} else if (quickOper == CJ) {
calculator.calculate();
if (!(boolean) calculator.getValue()) {
return readToEndAndSkipNextLineBlankChars(offset, command, null);
} else {
Integer jumpTo = m_P.get(offset);
if (jumpTo == null) {
return SKIP;
} else {
return jumpTo;
}
}
} else if (quickOper == JMP) {
Integer jumpTo = m_P.get(offset);
if (jumpTo == null) {
return SKIP;
} else {
return jumpTo;
}
} else if (quickOper == CALL) {
calculator.calculate();
if (!(boolean) calculator.getValue()) {
return readToEndAndSkipNextLineBlankChars(offset, command, null);
} else {
m_retV.push(calculator.getValue());
m_retP.push(offset);
Integer jumpTo = m_P.get(offset);
if (jumpTo == null) {
return SKIP;
} else {
return jumpTo;
}
}
} else if (quickOper == RET) {
Integer retP = m_retP.pop();
Object retV = m_retV.pop();
calculator.calculate();
calculator.setValue(retV);
retP = readToEndAndSkipNextLineBlankChars(retP, command, null);
return retP;
} else if (quickOper == END) {
return OVER;
}
calculator.binaryOperate(0, quickOper);
String quickArgs = m_quickArgs.get(offset);
if (quickArgs != null) {
calculator.setValue(quickArgs);
return readToEndAndSkipNextLineBlankChars(offset, command, null);
}
{
final String cmd = quickOper.toString();
m_operatorSetted = true;
int i = offset + cmd.length();
// 跳过分隔符
i = skipBlankChars(i, command);
++m_lineNumber;
if (!m_operatorSetted) {
return -1;
}
m_operatorSetted = false;
// 读取到换行
String[] sb = new String[1];
i = readToEndAndSkipNextLineBlankChars(i, command, sb);
calculator.setValue(sb[0]);
m_quickArgs.put(offset, sb[0]);
return i;
}
}
};
m_analysors.add(analysor);
}
private void addMef() {
addMepOrMef("MEF", false);
}
private void addMep() {
addMepOrMef("MEP", true);
}
private void addMepOrMef(String cmd, boolean isUp) {
Analysor<Object> analysor = new Analysor<Object>() {
@Override
public String toString() {
return cmd;
}
@Override
public int analyse(StandardCalculator<Object> calculator, String command, int offset) {
if (!command.startsWith(cmd, offset)) {
return SKIP;
}
BinaryOperator<Object> operator = new BinaryOperator<Object>() {
@Override
public String toString() {
return cmd;
}
public Object apply(Object a, Object b) {
DigitalPackage mepOrMef = m_mepOrMef.get(offset);
if (mepOrMef == null) {
mepOrMef = new DigitalPackage();
m_mepOrMef.put(offset, mepOrMef);
}
mepOrMef.transfer();
mepOrMef.set(toDigital(a));
if (isUp) {
return mepOrMef.isUp();
} else {
return mepOrMef.isDown();
}
}
};
m_quickOperators.put(offset, operator);
calculator.binaryOperate(0, operator);
int i = offset + cmd.length();
i = readToEndAndSkipNextLineBlankChars(i, command, null);
return i;
}
};
m_analysors.add(analysor);
}
private void addEnd() {
Analysor<Object> analysor = new Analysor<Object>() {
@Override
public String toString() {
return "END";
}
@Override
public int analyse(StandardCalculator<Object> calculator, String command, int offset) {
if (command.startsWith("END", offset)) {
m_quickOperators.put(offset, END);
return OVER;
} else {
return SKIP;
}
}
};
m_analysors.add(analysor);
}
private void addRET() {
Analysor<Object> analysor = new Analysor<Object>() {
@Override
public String toString() {
return "RET";
}
@Override
public int analyse(StandardCalculator<Object> calculator, String command, int offset) {
if (!command.startsWith("RET", offset)) {
return SKIP;
}
m_quickOperators.put(offset, RET);
Integer retP = m_retP.pop();
Object retV = m_retV.pop();
calculator.calculate();
calculator.setValue(retV);
retP = readToEndAndSkipNextLineBlankChars(retP, command, null);
return retP;
}
};
m_analysors.add(analysor);
}
private void addJUMP(String name, BinaryOperator<Object> operator, boolean conditional, boolean isCall) {
Analysor<Object> analysor = new Analysor<Object>() {
@Override
public String toString() {
return name;
}
@Override
public int analyse(StandardCalculator<Object> calculator, String command, int offset) {
if (!command.startsWith(name, offset)) {
return SKIP;
}
m_quickOperators.put(offset, operator);
m_blockLogicStack.clear();
calculator.calculate();
if (conditional && !(boolean) calculator.getValue()) {
return readToEndAndSkipNextLineBlankChars(offset, command, null);
}
if (isCall) {
m_retV.push(calculator.getValue());
m_retP.push(offset);
}
Integer idx = m_P.get(offset);
if (idx != null) {
return idx;
}
int i = offset + name.length();
i = skipBlankChars(i, command);
String[] pLabelBuilder = new String[1];
i = readToEndAndSkipNextLineBlankChars(i, command, pLabelBuilder);
String pLabel = pLabelBuilder[0];
idx = -1;
for (;;) {
idx = command.indexOf(pLabel, idx + 1);
if (idx == 0) {
break;
}
char c = command.charAt(idx - 2);
if (c < 'A' || (c > 'Z' && c < 'a') || c > 'z') {
break;
}
}
m_P.put(offset, idx);
return idx;
}
};
m_analysors.add(analysor);
}
/**
* 设置锁存器文件路径
*
* @param file
* 锁存文件
*/
public void setLockedMiddleRelayFile(File file) {
m_L = new FreeFileIO(file);
m_L.setLittleEndianAccodingToNative();
}
/**
* 设置锁存寄存器文件路径
*
* @param file
* 锁存文件
* @param offset
* 第一个锁存的寄存器地址
*/
public void setSavedDigister(File file, int offset) {
m_savedD = new FreeFileIO(file);
m_L.setLittleEndianAccodingToNative();
m_savedDOffset = offset;
}
public void setD(int key, Number value) {
if (key < m_savedDOffset) {
m_D.put(key, value);
} else {
if (m_savedD == null) {
StaticJavaUtils.exit("没有配置用于保存D点的文件");
}
m_savedD.writeDouble((key - m_savedDOffset) * Double.BYTES, value.doubleValue());
}
}
public Number getD(int key) {
if (key < m_savedDOffset) {
return m_D.getOrDefault(key, 0);
} else {
if (m_savedD == null) {
StaticJavaUtils.exit("没有配置用于保存D点的文件");
}
return m_savedD.readDouble((key - m_savedDOffset) * Double.BYTES);
}
}
private void setKM(int k, int key, long value) {
for (int i = 0; i < k * 4; ++i) {
setM(key + i, StaticDataUtils.getBit(value, i));
}
}
private long getKM(int k, int key) {
long value = 0;
for (int i = 0; i < k * 4; ++i) {
value = StaticDataUtils.setBit(value, i, getM(key + i));
}
return value;
}
public void setM(int key, boolean value) {
DigitalPackage pkg = m_M.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_M.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
public boolean getM(int key) {
return m_M.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setKL(int k, int key, long value) {
for (int i = 0; i < k * 4; ++i) {
setL(key + i, StaticDataUtils.getBit(value, i));
}
}
private long getKL(int k, int key) {
long value = 0;
for (int i = 0; i < k * 4; ++i) {
value = StaticDataUtils.setBit(value, i, getL(key + i));
}
return value;
}
private void setL(int key, boolean value) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
key *= 2;
boolean lastBit = m_L.readBit(key / 8, key % 8);
m_L.writeBit(key / 8, key % 8 + 1, lastBit);
m_L.writeBit(key / 8, key % 8, value);
}
private boolean getL(int key) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
key *= 2;
return m_L.readBit(key / 8, key % 8);
}
private void setSM(int key, boolean value) {
DigitalPackage pkg = m_SM.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_SM.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
private boolean getSM(int key) {
return m_SM.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setCC(int key, boolean value) {
DigitalPackage pkg = m_CC.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_CC.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
if (pkg.isUp()) {
long cn = getCN(key);
cn += 1;
setCN(key, cn);
}
}
@SuppressWarnings("unused")
private boolean getCC(int key) {
return m_CC.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setCLim(int key, long value) {
m_CLIMIT.put(key, value);
}
private long getCLim(int key) {
return m_CLIMIT.getOrDefault(key, (long) 0);
}
private void setCN(int key, long value) {
m_CN.put(key, value);
long cLim = getCLim(key);
setCS(key, value >= cLim);
}
private long getCN(int key) {
return m_CN.getOrDefault(key, (long) 0);
}
private void setCS(int key, boolean value) {
DigitalPackage pkg = m_CS.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_CS.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
private boolean getCS(int key) {
return m_CS.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setTC(int key, boolean value) {
DigitalPackage pkg = m_TC.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_TC.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
long tlim = getTLim(key);
if (pkg.get() == false) {
setTN(key, 0);
setTS(key, false);
return;
}
long tn = getTN(key);
if (tn > tlim) {
setTN(key, tlim);
}
setTS(key, tn >= tlim);
m_timer.start();
}
@SuppressWarnings("unused")
private boolean getTC(int key) {
return m_TC.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setTN(int key, long value) {
m_TN.put(key, value);
}
private long getTN(int key) {
return m_TN.getOrDefault(key, (long) 0);
}
private void setTLim(int key, long value) {
m_TLIMIT.put(key, value);
}
private long getTLim(int key) {
return m_TLIMIT.getOrDefault(key, (long) 0);
}
private void setTS(int key, boolean value) {
DigitalPackage pkg = m_TS.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_TS.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
private boolean getTS(int key) {
return m_TS.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
public void reset() {
m_P.clear();
m_skipWhiteSpace.clear();
m_quickOperators.clear();
m_quickArgs.clear();
}
@Override
public String toString() {
return "" + m_stackCalc.getValue();
}
public void calc(String string) {
m_blockLogicStack.clear();
m_mpsCommandStack.clear();
m_retP.clear();
m_retV.clear();
m_lineNumber = 0;
m_calc.calculate(string.toUpperCase());
}
private void addOperationNum() {
Analysor<Object> analysor = new Analysor<Object>() {
@Override
public String toString() {
return "";
}
@Override
public int analyse(StandardCalculator<Object> calculator, String command, int offset) {
++m_lineNumber;
if (!m_operatorSetted) {
return -1;
}
m_operatorSetted = false;
int i = offset;
// 读取到换行
String[] sb = new String[1];
i = readToEndAndSkipNextLineBlankChars(i, command, sb);
calculator.setValue(sb[0]);
return i;
}
};
m_analysors.add(analysor);
}
private void addOperator(String cmd, BinaryOperator<Object> operator) {
Analysor<Object> analysor = new Analysor<Object>() {
@Override
public String toString() {
return cmd;
}
@Override
public int analyse(StandardCalculator<Object> calculator, String command, int offset) {
if (!command.startsWith(cmd, offset)) {
return SKIP;
}
m_operatorSetted = true;
int i = offset + cmd.length();
// 跳过分隔符
i = skipBlankChars(i, command);
BinaryOperator<Object> namedOperator = new BinaryOperator<Object>() {
@Override
public String toString() {
return cmd;
}
@Override
public Object apply(Object t, Object u) {
return operator.apply(t, u);
}
};
calculator.binaryOperate(0, namedOperator);
m_quickOperators.put(offset, namedOperator);
return i;
}
};
m_analysors.add(analysor);
}
private static final boolean isCmdCharFound(char c) {
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
return true;
}
if ("+-*/".indexOf(c) >= 0) {
return true;
}
return false;
}
private int readToEndAndSkipNextLineBlankChars(int i, String command, String[] out) {
final int from = i;
if (out == null || out.length == 0) {
// 没有输出,可以直接跳到行尾
Integer to = m_skipWhiteSpace.get(i);
if (to != null) {
i = to;
} else {
for (; i < command.length(); ++i) {
char c = command.charAt(i);
if (c == '\r' || c == '\n') {
break;
}
}
for (; i < command.length(); ++i) {
char c = command.charAt(i);
if (isCmdCharFound(c)) {
break;
}
}
m_skipWhiteSpace.put(from, i);
}
return i;
} else {
// 有输出,需要复制,用查表法更慢,可能是JVM的优化造成的。
StringBuilder sb = new StringBuilder();
for (; i < command.length(); ++i) {
char c = command.charAt(i);
if (c == '\r' || c == '\n') {
break;
}
sb.append(c);
}
out[0] = sb.toString().trim();
// 跳过换行和下一行的缩进、行号
{
Integer to = m_skipWhiteSpace.get(i);
if (to != null) {
i = to;
} else {
int from2 = i;
for (; i < command.length(); ++i) {
char c = command.charAt(i);
if (isCmdCharFound(c)) {
break;
}
}
m_skipWhiteSpace.put(from2, i);
}
}
return i;
}
}
private int skipBlankChars(int i, String command) {
Integer to = m_skipWhiteSpace.get(i);
if (to != null) {
i = to;
} else {
int from = i;
for (; i < command.length(); ++i) {
char c = command.charAt(i);
if (SEPARATOR_IN_LINE.indexOf(c) < 0) {
break;
}
}
m_skipWhiteSpace.put(from, i);
}
return i;
}
private boolean toDigital(Object d) {
if (d instanceof Boolean) {
return (boolean) d;
}
String label = d.toString().toUpperCase();
if ("true".equalsIgnoreCase(label)) {
return true;
} else if ("false".equalsIgnoreCase(label)) {
return false;
}
if (label.startsWith("SM")) {
return getSM(Integer.parseInt(label.substring(2)));
} else if (label.startsWith("M")) {
return getM(Integer.parseInt(label.substring(1)));
} else if (label.startsWith("C")) {
return getCS(Integer.parseInt(label.substring(1)));
} else if (label.startsWith("T")) {
return getTS(Integer.parseInt(label.substring(1)));
} else if (label.startsWith("L")) {
int key = Integer.parseInt(label.substring(1));
return getL(key);
} else {
StaticJavaUtils.exit(label + " is not a digital");
return false;
}
}
private boolean toDigitalI(Object d) {
return !toDigital(d);
}
private boolean toDigitalP(Object d) {
String label = d.toString().toUpperCase();
if ("true".equalsIgnoreCase(label)) {
return true;
} else if ("false".equalsIgnoreCase(label)) {
return false;
}
if (label.startsWith("SM")) {
return m_SM.getOrDefault(Integer.parseInt(label.substring(2)), DigitalPackage.DEFAULT).isUp();
} else if (label.startsWith("M")) {
return m_M.getOrDefault(Integer.parseInt(label.substring(1)), DigitalPackage.DEFAULT).isUp();
} else if (label.startsWith("C")) {
return m_CS.getOrDefault(Integer.parseInt(label.substring(1)), DigitalPackage.DEFAULT).isUp();
} else if (label.startsWith("T")) {
return m_TS.getOrDefault(Integer.parseInt(label.substring(1)), DigitalPackage.DEFAULT).isUp();
} else if (label.startsWith("L")) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
int key = Integer.parseInt(label.substring(1)) * 2;
boolean current = m_L.readBit(key / 8, key % 8);
boolean last = m_L.readBit(key / 8, key % 8 + 1);
return current && !last;
} else {
StaticJavaUtils.exit(label + " is not a digital");
return false;
}
}
private boolean toDigitalPI(Object d) {
return !toDigitalP(d);
}
private boolean toDigitalF(Object d) {
String label = d.toString().toUpperCase();
if ("true".equalsIgnoreCase(label)) {
return true;
} else if ("false".equalsIgnoreCase(label)) {
return false;
}
if (label.startsWith("SM")) {
return m_SM.getOrDefault(Integer.parseInt(label.substring(2)), DigitalPackage.DEFAULT).isDown();
} else if (label.startsWith("M")) {
return m_M.getOrDefault(Integer.parseInt(label.substring(1)), DigitalPackage.DEFAULT).isDown();
} else if (label.startsWith("C")) {
return m_CS.getOrDefault(Integer.parseInt(label.substring(1)), DigitalPackage.DEFAULT).isDown();
} else if (label.startsWith("T")) {
return m_TS.getOrDefault(Integer.parseInt(label.substring(1)), DigitalPackage.DEFAULT).isDown();
} else if (label.startsWith("L")) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
int key = Integer.parseInt(label.substring(1)) * 2;
boolean current = m_L.readBit(key / 8, key % 8);
boolean last = m_L.readBit(key / 8, key % 8 + 1);
return !current && last;
} else {
StaticJavaUtils.exit(label + " is not a digital");
return false;
}
}
private boolean toDigitalFI(Object d) {
return !toDigitalF(d);
}
private Number toNumber(final String label) {
int radix = 10;
String n;
if (label.startsWith("K")) {
if (label.contains("M")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(label, "K%dM%d", nums);
return getKM(nums.get(0).intValue(), nums.get(1).intValue());
} else if (label.contains("L")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(label, "K%dL%d", nums);
return getKL(nums.get(0).intValue(), nums.get(1).intValue());
} else {
n = label.substring(1);
}
} else if (label.startsWith("H")) {
n = label.substring(1);
radix = 16;
} else if (label.startsWith("D")) {
n = label.substring(1);
return getD(Integer.parseInt(n));
} else if (label.startsWith("C")) {
n = label.substring(1);
return getCN(Integer.parseInt(n));
} else if (label.startsWith("T")) {
n = label.substring(1);
return getTN(Integer.parseInt(n));
} else {
StaticJavaUtils.exit(label + " is not a number");
return null;
}
try {
if (radix == 16) {
return Long.valueOf(n, radix);
} else {
return Double.valueOf(n);
}
} catch (NumberFormatException e) {
}
StaticJavaUtils.exit(label + " is not a number");
return null;
}
private void setNumber(String name, int offset, Number value) {
if (name.startsWith("K")) {
if (name.contains("M")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(name, "K%dM%d", nums);
setKM(nums.get(0).intValue(), nums.get(1).intValue(), value.longValue());
} else if (name.contains("L")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(name, "K%dL%d", nums);
setKL(nums.get(0).intValue(), nums.get(1).intValue(), value.longValue());
}
} else {
int index = Integer.parseInt(name.substring(1));
index += offset;
if (name.startsWith("D")) {
setD(index, value);
} else if (name.startsWith("C")) {
setCN(index, value.longValue());
} else if (name.startsWith("T")) {
setTN(index, value.longValue());
} else {
}
}
}
}
没有实现X和Y。在上位机上X和Y前缀没有意义,所以就直接不要了。也没有特殊功能寄存器。如果需要用到那些功能,干脆直接用Java或Python好了,Matlab也很好。这个三菱模拟器就是用来解决复杂的二值逻辑问题的。
再上个双行计算器标准模板,双行计算器是PLC核心算法的框架类,用于承载分析器。分析器中调用单行计算器。单行计算器是执行类。在单行计算器中可以通过Lambda方式添加一元操作符或二元操作符。不过代码太大,放上来也没人看得懂。本文只给出一个示范性的思路,并没有把PLC模拟器内核全部放进来。
package pers.laserpen.util.math.calculator.standardCalculator;
import java.util.Objects;
public final class DoubleLineCalculator<VALUE_TYPE> {
private StandardCalculator<VALUE_TYPE> m_calculator;
private Iterable<Analysor<VALUE_TYPE>> m_analysors;
public DoubleLineCalculator(StandardCalculator<VALUE_TYPE> calculator,
Iterable<Analysor<VALUE_TYPE>> analysors) {
m_calculator = Objects.requireNonNull(calculator);
m_analysors = Objects.requireNonNull(analysors);
}
/**
* 计算正确返回结果,计算错误返回null。<br/>
* 核心函数区分大小写,自带的操作符全为小写。<br/>
* 如有需要,请在调用前转换为全小写。【该注释是配套的科学计算器的注释,对应梯形图计算器应该是默认全大写】
*
* @param command
* @return
*/
public VALUE_TYPE calculate(String command) {
// 防止受上一次的结果干扰
m_calculator.reset();
int index = 0;
while (index < command.length()) {
boolean failed = true;
for (Analysor<VALUE_TYPE> analysor : m_analysors) {
int next = analysor.analyse(m_calculator, command, index);
if (next >= 0) {
index = next;
failed = false;
break;
}
}
if (failed) {
++index;
}
// System.out.println(m_calculator);
}
m_calculator.calculate();
if (m_calculator.isCorrect()) {
return m_calculator.getValue();
} else {
return null;
}
}
public StandardCalculator<VALUE_TYPE> getCalculator() {
return m_calculator;
}
public Iterable<Analysor<VALUE_TYPE>> getAnalysors() {
return m_analysors;
}
@Override
public String toString() {
return m_calculator.toString();
}
/**
* 算式分析器
*
* @author Laserpen
*/
@FunctionalInterface
public static interface Analysor<VALUE_TYPE> {
/** 跳过后面的字符串,结束扫描 */
public static final int OVER = Integer.MAX_VALUE;
/** 跳过当前扫描模块 */
public static final int SKIP = -1;
/**
* @param calculator
* 核心计算器
* @param command
* 算式。 传入完整算式,以支持跳转指令。
* @param offset
* 字符串索引偏移。绝对地址。
* @return >=0 分析成功,并返回下一个索引 <0 分析不成功。返回0表示回到原点,用于复位指令。
*/
public int analyse(StandardCalculator<VALUE_TYPE> calculator, String command, int offset);
}
}
由于命令长度超过1万行时,对跳转指令的操作需要很长的时间,又新增一个伪编译型的PLC虚拟机。
package pers.laserpen.util.automation.plcEmulator;
import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.*;
import java.util.function.*;
import pers.laserpen.util.data.StaticDataUtils;
import pers.laserpen.util.file.FreeFileIO;
import pers.laserpen.util.java.StaticJavaUtils;
import pers.laserpen.util.string.RegexBuilder;
import pers.laserpen.util.string.StaticStringUtils;
import pers.laserpen.util.thread.AccuracyTimer;
/**
* 伪编译型三菱PLC执行器
*
* @author Laserpen
*/
public class MitsubishiPLCRunner {
private static final String SEPARATOR_IN_LINE = ((Supplier<String>) () -> {
RegexBuilder regex = new RegexBuilder();
regex.appendCharGroup(" \"\t,,\' \ufeff\0\f", false);
return regex.toString();
}).get();
private Map<Integer, Number> m_D = new HashMap<>();
private FreeFileIO m_savedD = null;
private int m_savedDOffset = 0;
private Map<Integer, DigitalPackage> m_X = new HashMap<>();
private Map<Integer, DigitalPackage> m_Y = new HashMap<>();
private Map<Integer, DigitalPackage> m_M = new HashMap<>();
private FreeFileIO m_L = null;
private Map<Integer, DigitalPackage> m_SM = new HashMap<>();
private Map<Integer, DigitalPackage> m_mepOrMef = new HashMap<>();
private Map<Integer, DigitalPackage> m_CC = new HashMap<>();
private Map<Integer, Long> m_CN = new HashMap<>();
private Map<Integer, Long> m_CLIMIT = new HashMap<>();
private Map<Integer, DigitalPackage> m_CS = new HashMap<>();
private Map<Integer, DigitalPackage> m_TC = new HashMap<>();
private Map<Integer, Long> m_TN = new HashMap<>();
private Map<Integer, Long> m_TLIMIT = new HashMap<>();
private Map<Integer, DigitalPackage> m_TS = new HashMap<>();
private AccuracyTimer m_timer = new AccuracyTimer();
private AtomicLong m_tickTimerFlag = new AtomicLong();
private long m_addPlcTimerFlag = 0;
private Deque<Boolean> m_blockLogicStack = new ArrayDeque<>();
private Deque<Boolean> m_mpsCommandStack = new ArrayDeque<>();
private Deque<Integer> m_retPositionStack = new ArrayDeque<>();
private Deque<Boolean> m_retValueStack = new ArrayDeque<>();
private PLCCommand[] m_compileProgram = null;
private Map<String, Function<String[], PLCCommand>> m_compMap = new HashMap<>();
private int m_programPointer = 0;
public MitsubishiPLCRunner(long tickTime) {
if (tickTime <= 0) {
StaticJavaUtils.exit("不支持负的延时");
}
setSM(400, true);
setSM(401, false);
setM(8000, true);
setM(8001, false);
addOperators();
m_timer.setTask(ct -> {
if (m_tickTimerFlag.getAndIncrement() > 1000 / tickTime) {
m_tickTimerFlag.set(0);
// System.out.println("plc timer auto closed");
return 0;
} else {
return tickTime;
}
});
}
private void addOperators() {
m_compMap.put("LDP", sa -> {
if (sa.length < 2) {
return null;
}
final String key = sa[1];
BooleanSupplier sup = toDigitalPSupplier(key);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
return sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("LDPI", sa -> {
if (sa.length < 2) {
return null;
}
final String key = sa[1];
BooleanSupplier sup = toDigitalPISupplier(key);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
return sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("LDF", sa -> {
if (sa.length < 2) {
return null;
}
final String key = sa[1];
BooleanSupplier sup = toDigitalFSupplier(key);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
return sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("LDFI", sa -> {
if (sa.length < 2) {
return null;
}
final String key = sa[1];
BooleanSupplier sup = toDigitalFISupplier(key);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
return sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("LDI", sa -> {
if (sa.length < 2) {
return null;
}
final String key = sa[1];
BooleanSupplier sup = toDigitalISupplier(key);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
return sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("LD", sa -> {
if (sa.length < 2) {
return null;
}
final String key = sa[1];
BooleanSupplier sup = toDigitalSupplier(key);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
return sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("LD>", sa -> {
if (sa.length < 3) {
return null;
}
final String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
Number n1 = sup1.get();
Number n2 = sup2.get();
return n1.doubleValue() > n2.doubleValue();
};
return cmd;
});
m_compMap.put("LDD>", m_compMap.get("LD>"));
m_compMap.put("LD>=", sa -> {
if (sa.length < 3) {
return null;
}
final String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
Number n1 = sup1.get();
Number n2 = sup2.get();
return n1.doubleValue() >= n2.doubleValue();
};
return cmd;
});
m_compMap.put("LDD>=", m_compMap.get("LD>="));
m_compMap.put("LD<", sa -> {
if (sa.length < 3) {
return null;
}
final String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
Number n1 = sup1.get();
Number n2 = sup2.get();
return n1.doubleValue() < n2.doubleValue();
};
return cmd;
});
m_compMap.put("LDD<", m_compMap.get("LD<"));
m_compMap.put("LD<=", sa -> {
if (sa.length < 3) {
return null;
}
final String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
Number n1 = sup1.get();
Number n2 = sup2.get();
return n1.doubleValue() <= n2.doubleValue();
};
return cmd;
});
m_compMap.put("LDD<=", m_compMap.get("LD<="));
m_compMap.put("LD<>", sa -> {
if (sa.length < 3) {
return null;
}
final String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
Number n1 = sup1.get();
Number n2 = sup2.get();
return n1.doubleValue() != n2.doubleValue();
};
return cmd;
});
m_compMap.put("LDD<>", m_compMap.get("LD<>"));
m_compMap.put("LD=", sa -> {
if (sa.length < 3) {
return null;
}
final String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
m_blockLogicStack.push(b);
Number n1 = sup1.get();
Number n2 = sup2.get();
return n1.doubleValue() == n2.doubleValue();
};
return cmd;
});
m_compMap.put("LDD=", m_compMap.get("LD="));
m_compMap.put("OUT", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
int index = Integer.parseInt(key.substring(1));
PLCCommand cmd = null;
if (key.startsWith("M")) {
DigitalPackage pkg = m_M.get(index);
if (pkg == null) {
pkg = new DigitalPackage();
m_M.put(index, pkg);
}
DigitalPackage PKG = pkg;
cmd = b -> {
m_blockLogicStack.clear();
PKG.transfer();
PKG.set(b);
return b;
};
} else if (key.startsWith("X")) {
DigitalPackage pkg = m_X.get(index);
if (pkg == null) {
pkg = new DigitalPackage();
m_X.put(index, pkg);
}
DigitalPackage PKG = pkg;
cmd = b -> {
m_blockLogicStack.clear();
PKG.transfer();
PKG.set(b);
return b;
};
} else if (key.startsWith("Y")) {
DigitalPackage pkg = m_Y.get(index);
if (pkg == null) {
pkg = new DigitalPackage();
m_Y.put(index, pkg);
}
DigitalPackage PKG = pkg;
cmd = b -> {
m_blockLogicStack.clear();
PKG.transfer();
PKG.set(b);
return b;
};
} else if (key.startsWith("T")) {
if (sa.length < 3) {
return null;
}
String key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key2);
cmd = b -> {
m_blockLogicStack.clear();
setTLim(index, sup.get().longValue());
setTC(index, b);
return b;
};
} else if (key.startsWith("C")) {
if (sa.length < 3) {
return null;
}
String key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key2);
cmd = b -> {
m_blockLogicStack.clear();
setCLim(index, sup.get().longValue());
setCC(index, b);
return b;
};
} else if (key.startsWith("L")) {
cmd = b -> {
m_blockLogicStack.clear();
setL(index, b);
return b;
};
}
return cmd;
});
m_compMap.put("AND", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalSupplier(key);
PLCCommand cmd = b -> {
return b && sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ANI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalISupplier(key);
PLCCommand cmd = b -> {
return b && sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ANDP", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalPSupplier(key);
PLCCommand cmd = b -> {
return b && sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ANDPI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalPISupplier(key);
PLCCommand cmd = b -> {
return b && sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ANDF", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalFSupplier(key);
PLCCommand cmd = b -> {
return b && sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ANDFI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalFISupplier(key);
PLCCommand cmd = b -> {
return b && sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("AND<", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() < n2.doubleValue();
return b && b2;
};
return cmd;
});
m_compMap.put("ANDD<", m_compMap.get("AND<"));
m_compMap.put("AND<=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() <= n2.doubleValue();
return b && b2;
};
return cmd;
});
m_compMap.put("ANDD<=", m_compMap.get("AND<="));
m_compMap.put("AND>", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() > n2.doubleValue();
return b && b2;
};
return cmd;
});
m_compMap.put("ANDD>", m_compMap.get("AND>"));
m_compMap.put("AND>=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() >= n2.doubleValue();
return b && b2;
};
return cmd;
});
m_compMap.put("ANDD>=", m_compMap.get("AND>="));
m_compMap.put("AND<>", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() != n2.doubleValue();
return b && b2;
};
return cmd;
});
m_compMap.put("ANDD<>", m_compMap.get("AND<>"));
m_compMap.put("AND=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() == n2.doubleValue();
return b && b2;
};
return cmd;
});
m_compMap.put("ANDD=", m_compMap.get("AND="));
m_compMap.put("OR", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalSupplier(key);
PLCCommand cmd = b -> {
return b || sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ORI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalISupplier(key);
PLCCommand cmd = b -> {
return b || sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ORP", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalPSupplier(key);
PLCCommand cmd = b -> {
return b || sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ORPI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalPISupplier(key);
PLCCommand cmd = b -> {
return b || sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ORF", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalFSupplier(key);
PLCCommand cmd = b -> {
return b || sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("ORFI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalFISupplier(key);
PLCCommand cmd = b -> {
return b || sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("OR<", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() < n2.doubleValue();
return b || b2;
};
return cmd;
});
m_compMap.put("ORD<", m_compMap.get("OR<"));
m_compMap.put("OR<=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() <= n2.doubleValue();
return b || b2;
};
return cmd;
});
m_compMap.put("ORD<=", m_compMap.get("OR<="));
m_compMap.put("OR>", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() > n2.doubleValue();
return b || b2;
};
return cmd;
});
m_compMap.put("ORD>", m_compMap.get("OR>"));
m_compMap.put("OR>=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() >= n2.doubleValue();
return b || b2;
};
return cmd;
});
m_compMap.put("ORD>=", m_compMap.get("OR>="));
m_compMap.put("OR<>", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() != n2.doubleValue();
return b || b2;
};
return cmd;
});
m_compMap.put("ORD<>", m_compMap.get("OR<>"));
m_compMap.put("OR=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() == n2.doubleValue();
return b || b2;
};
return cmd;
});
m_compMap.put("ORD=", m_compMap.get("OR="));
m_compMap.put("XOR", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalSupplier(key);
PLCCommand cmd = b -> {
return b != sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("XORI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalISupplier(key);
PLCCommand cmd = b -> {
return b != sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("XORP", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalPSupplier(key);
PLCCommand cmd = b -> {
return b != sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("XORPI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalPISupplier(key);
PLCCommand cmd = b -> {
return b != sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("XORF", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalFSupplier(key);
PLCCommand cmd = b -> {
return b != sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("XORFI", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
BooleanSupplier sup = toDigitalFISupplier(key);
PLCCommand cmd = b -> {
return b != sup.getAsBoolean();
};
return cmd;
});
m_compMap.put("XOR<", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() < n2.doubleValue();
return b != b2;
};
return cmd;
});
m_compMap.put("XORD<", m_compMap.get("XOR<"));
m_compMap.put("XOR<=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() <= n2.doubleValue();
return b != b2;
};
return cmd;
});
m_compMap.put("XORD<=", m_compMap.get("XOR<="));
m_compMap.put("XOR>", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() > n2.doubleValue();
return b != b2;
};
return cmd;
});
m_compMap.put("XORD>", m_compMap.get("XOR>"));
m_compMap.put("XOR>=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() >= n2.doubleValue();
return b != b2;
};
return cmd;
});
m_compMap.put("XORD>=", m_compMap.get("XOR>="));
m_compMap.put("XOR<>", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() != n2.doubleValue();
return b != b2;
};
return cmd;
});
m_compMap.put("XORD<>", m_compMap.get("XOR<>"));
m_compMap.put("XOR=", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
PLCCommand cmd = b -> {
Number n1 = sup1.get();
Number n2 = sup2.get();
boolean b2 = n1.doubleValue() == n2.doubleValue();
return b != b2;
};
return cmd;
});
m_compMap.put("XORD=", m_compMap.get("XOR="));
m_compMap.put("ANB", sa -> {
PLCCommand cmd = b -> {
return b & (boolean) m_blockLogicStack.pop();
};
return cmd;
});
m_compMap.put("ORB", sa -> {
PLCCommand cmd = b -> {
return b | (boolean) m_blockLogicStack.pop();
};
return cmd;
});
m_compMap.put("XORB", sa -> {
PLCCommand cmd = b -> {
return b != (boolean) m_blockLogicStack.pop();
};
return cmd;
});
m_compMap.put("MPS", sa -> {
PLCCommand cmd = b -> {
m_mpsCommandStack.push(b);
return b;
};
return cmd;
});
m_compMap.put("MPP", sa -> {
PLCCommand cmd = b -> {
return (boolean) m_mpsCommandStack.pop();
};
return cmd;
});
m_compMap.put("MPD", sa -> {
PLCCommand cmd = b -> {
return (boolean) m_mpsCommandStack.peek();
};
return cmd;
});
m_compMap.put("INV", sa -> {
PLCCommand cmd = b -> {
return !b;
};
return cmd;
});
m_compMap.put("SET", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
int index = Integer.parseInt(key.substring(1));
PLCCommand cmd = null;
if (key.startsWith("M")) {
DigitalPackage pkg = m_M.get(index);
if (pkg == null) {
pkg = new DigitalPackage();
m_M.put(index, pkg);
}
DigitalPackage PKG = pkg;
cmd = b -> {
m_blockLogicStack.clear();
if (b) {
PKG.transfer();
PKG.set(true);
}
return b;
};
} else if (key.startsWith("L")) {
cmd = b -> {
m_blockLogicStack.clear();
if (b) {
setL(index, true);
}
return b;
};
}
return cmd;
});
m_compMap.put("RST", sa -> {
if (sa.length < 2) {
return null;
}
String key = sa[1];
int index = Integer.parseInt(key.substring(1));
PLCCommand cmd = null;
if (key.startsWith("M")) {
DigitalPackage pkg = m_M.get(index);
if (pkg == null) {
pkg = new DigitalPackage();
m_M.put(index, pkg);
}
DigitalPackage PKG = pkg;
cmd = b -> {
m_blockLogicStack.clear();
if (b) {
PKG.transfer();
PKG.set(false);
}
return b;
};
} else if (key.startsWith("L")) {
cmd = b -> {
m_blockLogicStack.clear();
if (b) {
setL(index, false);
}
return b;
};
} else {
Consumer<Number> con = setNumberConsumer(key, 0);
cmd = b -> {
m_blockLogicStack.clear();
if (b) {
con.accept(0);
}
return b;
};
}
return cmd;
});
m_compMap.put("MOV", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number value = sup.get();
con.accept(value);
}
return b;
};
return cmd;
});
m_compMap.put("DMOV", m_compMap.get("MOV"));
m_compMap.put("WAND", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2], key3 = sa.length == 3 ? key2 : sa[3];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
Consumer<Number> con = setNumberConsumer(key3, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number addition1 = sup1.get();
Number addition2 = sup2.get();
Number ans = addition1.longValue() & addition2.longValue();
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("DAND", m_compMap.get("WAND"));
m_compMap.put("WOR", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2], key3 = sa.length == 3 ? key2 : sa[3];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
Consumer<Number> con = setNumberConsumer(key3, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number addition1 = sup1.get();
Number addition2 = sup2.get();
Number ans = addition1.longValue() | addition2.longValue();
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("DOR", m_compMap.get("WOR"));
m_compMap.put("WXOR", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2], key3 = sa.length == 3 ? key2 : sa[3];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
Consumer<Number> con = setNumberConsumer(key3, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number addition1 = sup1.get();
Number addition2 = sup2.get();
Number ans = addition1.longValue() ^ addition2.longValue();
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("DXOR", m_compMap.get("WXOR"));
m_compMap.put("CML", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number num = sup.get();
Number ans = ~num.longValue();
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("DCML", m_compMap.get("CML"));
m_compMap.put("NEG", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number num = sup.get();
Number ans = -num.doubleValue();
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("DNEG", m_compMap.get("NEG"));
m_compMap.put("ADD", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2], key3 = sa.length == 3 ? key2 : sa[3];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
Consumer<Number> con = setNumberConsumer(key3, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number addition1 = sup1.get();
Number addition2 = sup2.get();
Number ans = addition1.doubleValue() + addition2.doubleValue();
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("+", m_compMap.get("ADD"));
m_compMap.put("D+", m_compMap.get("ADD"));
m_compMap.put("SUB", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2], key3 = sa.length == 3 ? key2 : sa[3];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
Consumer<Number> con = setNumberConsumer(key3, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number addition1 = sup1.get();
Number addition2 = sup2.get();
Number ans = addition1.doubleValue() - addition2.doubleValue();
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("-", m_compMap.get("SUB"));
m_compMap.put("D-", m_compMap.get("SUB"));
m_compMap.put("MUL", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2], key3 = sa.length == 3 ? key2 : sa[3];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
Consumer<Number> con = setNumberConsumer(key3, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number addition1 = sup1.get();
Number addition2 = sup2.get();
Number ans = addition1.doubleValue() * addition2.doubleValue();
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("*", m_compMap.get("MUL"));
m_compMap.put("D*", m_compMap.get("MUL"));
m_compMap.put("DIV", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2], key3 = sa.length == 3 ? key2 : sa[3];
Supplier<Number> sup1 = toNumberSupplier(key1);
Supplier<Number> sup2 = toNumberSupplier(key2);
Consumer<Number> con = setNumberConsumer(key3, 0);
Consumer<Number> conMod = setNumberConsumer(key3, 1);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number addition1 = sup1.get();
Number addition2 = sup2.get();
Number ans = addition1.doubleValue() / addition2.doubleValue();
Number ansMod = addition1.doubleValue() % addition2.doubleValue();
con.accept(ans);
conMod.accept(ansMod);
}
return b;
};
return cmd;
});
m_compMap.put("/", m_compMap.get("DIV"));
m_compMap.put("D/", m_compMap.get("DIV"));
m_compMap.put("SIN", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.sin(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("COS", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.cos(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("TAN", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.tan(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("ASIN", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.asin(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("ACOS", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.acos(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("ATAN", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.atan(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("EXP", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.exp(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("LOG", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.log(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("LOG10", sa -> {
if (sa.length < 3) {
return null;
}
String key1 = sa[1], key2 = sa[2];
Supplier<Number> sup = toNumberSupplier(key1);
Consumer<Number> con = setNumberConsumer(key2, 0);
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
if (b) {
Number x = sup.get();
double ans = Math.log10(x.doubleValue());
con.accept(ans);
}
return b;
};
return cmd;
});
m_compMap.put("CJ", sa -> {
if (sa.length < 2) {
return null;
}
String position = sa[1];
PLCJump cmd = new PLCJump() {
private int jump = Integer.MAX_VALUE;
@Override
public boolean execute(boolean enabled) {
m_blockLogicStack.clear();
if (enabled) {
m_programPointer = jump;
}
return enabled;
}
@Override
public void setJumpIndex(int index) {
jump = index;
}
@Override
public String getPositionFlag() {
return position;
}
};
return cmd;
});
m_compMap.put("JMP", sa -> {
if (sa.length < 2) {
return null;
}
String position = sa[1];
PLCJump cmd = new PLCJump() {
private int jump = Integer.MAX_VALUE;
@Override
public boolean execute(boolean enabled) {
m_blockLogicStack.clear();
m_programPointer = jump;
return enabled;
}
@Override
public void setJumpIndex(int index) {
jump = index;
}
@Override
public String getPositionFlag() {
return position;
}
};
return cmd;
});
m_compMap.put("CALL", sa -> {
if (sa.length < 2) {
return null;
}
String position = sa[1];
PLCJump cmd = new PLCJump() {
private int jump = Integer.MAX_VALUE;
@Override
public boolean execute(boolean enabled) {
m_blockLogicStack.clear();
if (enabled) {
m_retValueStack.push(enabled);
m_retPositionStack.push(m_programPointer);
m_programPointer = jump;
}
return enabled;
}
@Override
public void setJumpIndex(int index) {
jump = index;
}
@Override
public String getPositionFlag() {
return position;
}
};
return cmd;
});
m_compMap.put("RET", sa -> {
PLCCommand cmd = b -> {
m_blockLogicStack.clear();
boolean lastEnabled = (boolean) m_retValueStack.pop();
m_programPointer = m_retPositionStack.pop();
return lastEnabled;
};
return cmd;
});
m_compMap.put("END", sa -> {
PLCCommand cmd = b -> {
m_programPointer = m_compileProgram.length;
return b;
};
return cmd;
});
m_compMap.put("MEP", sa -> {
PLCCommand cmd = b -> {
DigitalPackage mepOrMef = m_mepOrMef.get(m_programPointer);
if (mepOrMef == null) {
mepOrMef = new DigitalPackage();
m_mepOrMef.put(m_programPointer, mepOrMef);
}
mepOrMef.transfer();
mepOrMef.set(b);
return mepOrMef.isUp();
};
return cmd;
});
m_compMap.put("MEF", sa -> {
PLCCommand cmd = b -> {
DigitalPackage mepOrMef = m_mepOrMef.get(m_programPointer);
if (mepOrMef == null) {
mepOrMef = new DigitalPackage();
m_mepOrMef.put(m_programPointer, mepOrMef);
}
mepOrMef.transfer();
mepOrMef.set(b);
return mepOrMef.isDown();
};
return cmd;
});
}
/**
* 编译
*
* @param program
* @return true 成功 false 失败
*/
public boolean compile(String program) {
BufferedReader reader;
{
StringReader reader2 = new StringReader(program);
reader = new BufferedReader(reader2);
}
List<PLCCommand> compileList = new ArrayList<>(65535);
List<PLCJump> jumpList = new ArrayList<>(8192);
Map<String, Integer> jumpPositionIndex = new HashMap<>(8192);
try {
for (;;) {
String line = reader.readLine();
if (line == null) {
break;
}
boolean ok = compileLine(compileList, jumpList, jumpPositionIndex, line);
if (!ok) {
System.err.println("编译失败,第" + (compileList.size() - 1) + "行");
return false;
}
}
for (PLCJump jump : jumpList) {
String flag = jump.getPositionFlag();
Integer position = jumpPositionIndex.get(flag);
if (position == null) {
System.err.println("链接失败,没有找到标签" + flag);
return false;
}
jump.setJumpIndex(position);
}
m_compileProgram = compileList.toArray(new PLCCommand[compileList.size()]);
return true;
} catch (Throwable t) {
t.printStackTrace();
}
return false;
}
private boolean compileLine(List<PLCCommand> compileList, List<PLCJump> jumpList,
Map<String, Integer> jumpPositionIndex,
String line) {
{
int index = 0;
for (;; ++index) {
if (index >= line.length()) {
// 跳过空行
return true;
}
char c = line.charAt(index);
if (isCmdCharFound(c)) {
line = line.substring(index);
break;
}
}
}
{
if (line.startsWith("P")) {
String pNumberStr = line.trim().substring(1);
try {
Integer.parseInt(pNumberStr);
jumpPositionIndex.put(line.trim(), compileList.size());
// 找到了标签
return true;
} catch (NumberFormatException e) {
}
}
}
{
String[] subLine = line.split(SEPARATOR_IN_LINE);
String cmdStr = subLine[0];
Function<String[], PLCCommand> cmdBuilder = m_compMap.get(cmdStr);
if (cmdBuilder == null) {
return false;
}
PLCCommand plccmd = cmdBuilder.apply(subLine);
if (plccmd == null) {
return false;
}
compileList.add(plccmd);
if (plccmd instanceof PLCJump) {
PLCJump plcjmp = (PLCJump) plccmd;
jumpList.add(plcjmp);
}
return true;
}
}
/**
* 设置锁存器文件路径
*
* @param file
* 锁存文件
*/
public void setLockedMiddleRelayFile(File file) {
if (file == null) {
m_L = null;
} else {
m_L = new FreeFileIO(file);
m_L.setLittleEndian(true);
}
}
/**
* 设置锁存寄存器文件路径
*
* @param file
* 锁存文件
* @param offset
* 第一个锁存的寄存器地址
*/
public void setSavedDigister(File file, int offset) {
if (file == null || offset < 0) {
m_savedD = null;
m_savedDOffset = -1;
} else {
m_savedD = new FreeFileIO(file);
m_savedD.setLittleEndian(true);
m_savedDOffset = offset;
}
}
public void setD(int key, Number value) {
if (m_savedD == null || key < m_savedDOffset) {
m_D.put(key, value);
} else {
m_savedD.writeDouble((key - m_savedDOffset) * Double.BYTES, value.doubleValue());
}
}
public Number getD(int key) {
if (m_savedD == null || key < m_savedDOffset) {
return m_D.getOrDefault(key, 0);
} else {
return m_savedD.readDouble((key - m_savedDOffset) * Double.BYTES);
}
}
private void setKX(int k, int key, long value) {
for (int i = 0; i < k * 4; ++i) {
setX(key + i, StaticDataUtils.getBit(value, i));
}
}
private long getKX(int k, int key) {
long value = 0;
for (int i = 0; i < k * 4; ++i) {
value = StaticDataUtils.setBit(value, i, getX(key + i));
}
return value;
}
public void setX(int key, boolean value) {
DigitalPackage pkg = m_X.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_X.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
public boolean getX(int key) {
return m_X.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setKY(int k, int key, long value) {
for (int i = 0; i < k * 4; ++i) {
setY(key + i, StaticDataUtils.getBit(value, i));
}
}
private long getKY(int k, int key) {
long value = 0;
for (int i = 0; i < k * 4; ++i) {
value = StaticDataUtils.setBit(value, i, getY(key + i));
}
return value;
}
public void setY(int key, boolean value) {
DigitalPackage pkg = m_Y.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_Y.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
public boolean getY(int key) {
return m_Y.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setKM(int k, int key, long value) {
for (int i = 0; i < k * 4; ++i) {
setM(key + i, StaticDataUtils.getBit(value, i));
}
}
private long getKM(int k, int key) {
long value = 0;
for (int i = 0; i < k * 4; ++i) {
value = StaticDataUtils.setBit(value, i, getM(key + i));
}
return value;
}
public void setM(int key, boolean value) {
DigitalPackage pkg = m_M.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_M.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
public boolean getM(int key) {
return m_M.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setKL(int k, int key, long value) {
for (int i = 0; i < k * 4; ++i) {
setL(key + i, StaticDataUtils.getBit(value, i));
}
}
private long getKL(int k, int key) {
long value = 0;
for (int i = 0; i < k * 4; ++i) {
value = StaticDataUtils.setBit(value, i, getL(key + i));
}
return value;
}
private void setL(int key, boolean value) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
key *= 2;
boolean lastBit = m_L.readBit(key / 8, key % 8);
m_L.writeBit(key / 8, key % 8 + 1, lastBit);
m_L.writeBit(key / 8, key % 8, value);
}
private boolean getL(int key) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
key *= 2;
return m_L.readBit(key / 8, key % 8);
}
private void setSM(int key, boolean value) {
DigitalPackage pkg = m_SM.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_SM.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
@SuppressWarnings("unused")
private boolean getSM(int key) {
return m_SM.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setCC(int key, boolean value) {
DigitalPackage pkg = m_CC.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_CC.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
if (pkg.isUp()) {
long cn = getCN(key);
cn += 1;
setCN(key, cn);
}
}
private void setCLim(int key, long value) {
m_CLIMIT.put(key, value);
}
private long getCLim(int key) {
return m_CLIMIT.getOrDefault(key, (long) 0);
}
private void setCN(int key, long value) {
m_CN.put(key, value);
long cLim = getCLim(key);
setCS(key, value >= cLim);
}
private long getCN(int key) {
return m_CN.getOrDefault(key, (long) 0);
}
private void setCS(int key, boolean value) {
DigitalPackage pkg = m_CS.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_CS.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
@SuppressWarnings("unused")
private boolean getCS(int key) {
return m_CS.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
private void setTC(int key, boolean value) {
DigitalPackage pkg = m_TC.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_TC.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
if (value == false) {
setTN(key, 0);
setTS(key, false);
return;
}
if (m_addPlcTimerFlag > 0) {
long tlim = getTLim(key);
long tn = getTN(key);
tn += m_addPlcTimerFlag;
if (tn > tlim) {
tn = tlim;
}
setTN(key, tn);
}
}
private void setTN(int key, long value) {
m_TN.put(key, value);
long tLim = getTLim(key);
setTS(key, value >= tLim);
}
private long getTN(int key) {
return m_TN.getOrDefault(key, (long) 0);
}
private void setTLim(int key, long value) {
m_TLIMIT.put(key, value);
}
private long getTLim(int key) {
return m_TLIMIT.getOrDefault(key, (long) 0);
}
private void setTS(int key, boolean value) {
DigitalPackage pkg = m_TS.get(key);
if (pkg == null) {
pkg = new DigitalPackage();
m_TS.put(key, pkg);
}
pkg.transfer();
pkg.set(value);
}
@SuppressWarnings("unused")
private boolean getTS(int key) {
return m_TS.getOrDefault(key, DigitalPackage.DEFAULT).get();
}
public void clearMemory() {
m_CC = new HashMap<>();
m_CLIMIT = new HashMap<>();
m_CN = new HashMap<>();
m_CS = new HashMap<>();
m_TC = new HashMap<>();
m_TLIMIT = new HashMap<>();
m_TN = new HashMap<>();
m_TS = new HashMap<>();
m_M = new HashMap<>();
setM(8000, true);
setM(8001, false);
m_D = new HashMap<>();
m_mepOrMef = new HashMap<>();
m_timer.stop();
m_tickTimerFlag.set(0);
}
@Override
public String toString() {
return super.toString();
}
public void execute() {
if (m_compileProgram == null) {
StaticJavaUtils.exit("没有编译程序");
}
m_timer.start(r -> {
Thread t = new Thread(r);
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY);
return t;
});
m_addPlcTimerFlag = m_tickTimerFlag.getAndSet(0);
boolean primarySignal = false;
m_programPointer = 0;
for (;;) {
if (m_programPointer < 0) {
break;
} else if (m_programPointer >= m_compileProgram.length) {
break;
}
PLCCommand cmd = m_compileProgram[m_programPointer++];
primarySignal = cmd.execute(primarySignal);
}
m_addPlcTimerFlag = 0;
m_blockLogicStack.clear();
m_mpsCommandStack.clear();
m_retPositionStack.clear();
m_retValueStack.clear();
}
private static final boolean isCmdCharFound(char c) {
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
return true;
}
if ("+-*/".indexOf(c) >= 0) {
return true;
}
return false;
}
private BooleanSupplier toDigitalSupplier(Object d) {
if (d instanceof Boolean) {
return () -> (boolean) d;
}
String label = d.toString().toUpperCase();
if ("true".equalsIgnoreCase(label)) {
return () -> true;
} else if ("false".equalsIgnoreCase(label)) {
return () -> false;
}
if (label.startsWith("SM")) {
DigitalPackage pkg = m_SM.get(Integer.parseInt(label.substring(2)));
if (pkg == null) {
pkg = new DigitalPackage();
m_SM.put(Integer.parseInt(label.substring(2)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.get();
} else if (label.startsWith("X")) {
DigitalPackage pkg = m_X.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_X.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.get();
} else if (label.startsWith("Y")) {
DigitalPackage pkg = m_Y.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_Y.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.get();
} else if (label.startsWith("M")) {
DigitalPackage pkg = m_M.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_M.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.get();
} else if (label.startsWith("C")) {
DigitalPackage pkg = m_CS.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_CS.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.get();
} else if (label.startsWith("T")) {
DigitalPackage pkg = m_TS.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_TS.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.get();
} else if (label.startsWith("L")) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
int key = Integer.parseInt(label.substring(1)) * 2;
return () -> m_L.readBit(key / 8, key % 8);
} else {
StaticJavaUtils.exit(label + " is not a digital");
return null;
}
}
private BooleanSupplier toDigitalISupplier(Object d) {
BooleanSupplier sup = toDigitalSupplier(d);
return () -> !sup.getAsBoolean();
}
private BooleanSupplier toDigitalPSupplier(Object d) {
String label = d.toString().toUpperCase();
if ("true".equalsIgnoreCase(label)) {
return () -> true;
} else if ("false".equalsIgnoreCase(label)) {
return () -> false;
}
if (label.startsWith("SM")) {
DigitalPackage pkg = m_SM.get(Integer.parseInt(label.substring(2)));
if (pkg == null) {
pkg = new DigitalPackage();
m_SM.put(Integer.parseInt(label.substring(2)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isUp();
} else if (label.startsWith("X")) {
DigitalPackage pkg = m_X.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_X.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isUp();
} else if (label.startsWith("Y")) {
DigitalPackage pkg = m_Y.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_Y.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isUp();
} else if (label.startsWith("M")) {
DigitalPackage pkg = m_M.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_M.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isUp();
} else if (label.startsWith("C")) {
DigitalPackage pkg = m_CS.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_CS.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isUp();
} else if (label.startsWith("T")) {
DigitalPackage pkg = m_TS.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_TS.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isUp();
} else if (label.startsWith("L")) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
int key = Integer.parseInt(label.substring(1)) * 2;
return () -> {
boolean current = m_L.readBit(key / 8, key % 8);
boolean last = m_L.readBit(key / 8, key % 8 + 1);
return current && !last;
};
} else {
StaticJavaUtils.exit(label + " is not a digital");
return null;
}
}
private BooleanSupplier toDigitalPISupplier(Object d) {
BooleanSupplier sup = toDigitalPSupplier(d);
return () -> !sup.getAsBoolean();
}
private BooleanSupplier toDigitalFSupplier(Object d) {
String label = d.toString().toUpperCase();
if ("true".equalsIgnoreCase(label)) {
return () -> true;
} else if ("false".equalsIgnoreCase(label)) {
return () -> false;
}
if (label.startsWith("SM")) {
DigitalPackage pkg = m_SM.get(Integer.parseInt(label.substring(2)));
if (pkg == null) {
pkg = new DigitalPackage();
m_SM.put(Integer.parseInt(label.substring(2)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isDown();
} else if (label.startsWith("X")) {
DigitalPackage pkg = m_X.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_X.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isDown();
} else if (label.startsWith("Y")) {
DigitalPackage pkg = m_Y.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_Y.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isDown();
} else if (label.startsWith("M")) {
DigitalPackage pkg = m_M.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_M.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isDown();
} else if (label.startsWith("C")) {
DigitalPackage pkg = m_CS.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_CS.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isDown();
} else if (label.startsWith("T")) {
DigitalPackage pkg = m_TS.get(Integer.parseInt(label.substring(1)));
if (pkg == null) {
pkg = new DigitalPackage();
m_TS.put(Integer.parseInt(label.substring(1)), pkg);
}
DigitalPackage PKG = pkg;
return () -> PKG.isDown();
} else if (label.startsWith("L")) {
if (m_L == null) {
StaticJavaUtils.exit("没有配置用于保存L点的文件");
}
int key = Integer.parseInt(label.substring(1)) * 2;
return () -> {
boolean current = m_L.readBit(key / 8, key % 8);
boolean last = m_L.readBit(key / 8, key % 8 + 1);
return current && !last;
};
} else {
StaticJavaUtils.exit(label + " is not a digital");
return null;
}
}
private BooleanSupplier toDigitalFISupplier(Object d) {
BooleanSupplier sup = toDigitalFSupplier(d);
return () -> !sup.getAsBoolean();
}
private Supplier<Number> toNumberSupplier(final String label) {
int radix = 10;
String n;
if (label.startsWith("K")) {
if (label.contains("M")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(label, "K%dM%d", nums);
int i1 = nums.get(0).intValue();
int i2 = nums.get(1).intValue();
return () -> getKM(i1, i2);
} else if (label.contains("L")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(label, "K%dL%d", nums);
int i1 = nums.get(0).intValue();
int i2 = nums.get(1).intValue();
return () -> getKL(i1, i2);
} else if (label.contains("X")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(label, "K%dX%d", nums);
int i1 = nums.get(0).intValue();
int i2 = nums.get(1).intValue();
return () -> getKX(i1, i2);
} else if (label.contains("Y")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(label, "K%dY%d", nums);
int i1 = nums.get(0).intValue();
int i2 = nums.get(1).intValue();
return () -> getKY(i1, i2);
} else {
n = label.substring(1);
}
} else if (label.startsWith("H")) {
n = label.substring(1);
radix = 16;
} else if (label.startsWith("D")) {
n = label.substring(1);
int key = Integer.parseInt(n);
if (m_savedD == null || key < m_savedDOffset) {
return () -> m_D.getOrDefault(key, 0);
} else {
return () -> m_savedD.readDouble((key - m_savedDOffset) * Double.BYTES);
}
} else if (label.startsWith("C")) {
n = label.substring(1);
int key = Integer.parseInt(n);
return () -> m_CN.getOrDefault(key, (long) 0);
} else if (label.startsWith("T")) {
n = label.substring(1);
int key = Integer.parseInt(n);
return () -> m_TN.getOrDefault(key, (long) 0);
} else {
n = label;
}
try {
if (radix == 16) {
long value = Long.parseLong(n, radix);
return () -> value;
} else {
double value = Double.parseDouble(n);
return () -> value;
}
} catch (NumberFormatException e) {
}
StaticJavaUtils.exit(label + " is not a number");
return null;
}
private Consumer<Number> setNumberConsumer(String name, int offset) {
if (name.startsWith("K")) {
if (name.contains("M")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(name, "K%dM%d", nums);
int i1 = nums.get(0).intValue();
int i2 = nums.get(1).intValue();
return value -> setKM(i1, i2, value.longValue());
} else if (name.contains("L")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(name, "K%dL%d", nums);
int i1 = nums.get(0).intValue();
int i2 = nums.get(1).intValue();
return value -> setKL(i1, i2, value.longValue());
} else if (name.contains("X")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(name, "K%dX%d", nums);
int i1 = nums.get(0).intValue();
int i2 = nums.get(1).intValue();
return value -> setKX(i1, i2, value.longValue());
} else if (name.contains("Y")) {
List<Number> nums = new ArrayList<>();
StaticStringUtils.sscanf(name, "K%dY%d", nums);
int i1 = nums.get(0).intValue();
int i2 = nums.get(1).intValue();
return value -> setKY(i1, i2, value.longValue());
}
} else {
int index = Integer.parseInt(name.substring(1)) + offset;
if (name.startsWith("D")) {
if (m_savedD == null || index < m_savedDOffset) {
return value -> m_D.put(index, value);
} else {
return value -> m_savedD.writeDouble((index - m_savedDOffset) * Double.BYTES, value.doubleValue());
}
} else if (name.startsWith("C")) {
return value -> setCN(index, value.longValue());
} else if (name.startsWith("T")) {
return value -> setTN(index, value.longValue());
} else {
StaticJavaUtils.exit(name + " is not a number");
}
}
return null;
}
}