source: EcnlProtoTool/trunk/webapp/webmrbc/Ecnl/EObjectBlock.cs@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csharp
File size: 32.4 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using Bridge;
6using Bridge.Linq;
7using Bridge.Html5;
8
9namespace WebMrbc
10{
11 [IgnoreCast]
12 public class ENodeInitializeBlock : Block
13 {
14 public const string type_name = "enode_initialize";
15 internal EObjectWorkspace workspace_;
16
17 public ENodeInitializeBlock()
18 : base(type_name)
19 {
20 }
21
22 public void init()
23 {
24 this.appendDummyInput()
25 .appendField("初期化処理");
26 this.appendStatementInput("DO")
27 .setCheck(null);
28 this.setColour(230);
29 this.setTooltip("");
30 this.setHelpUrl("");
31 }
32
33 internal void OnCreate(EObjectWorkspace workspace, Create cre)
34 {
35 workspace_ = workspace;
36 }
37
38 internal void OnChange(EObjectWorkspace workspace, Change chg)
39 {
40 }
41
42 internal void OnDelete(EObjectWorkspace workspace, Delete del)
43 {
44 }
45
46 internal void OnMove(EObjectWorkspace workspace, Move mov)
47 {
48 }
49 }
50
51 [IgnoreCast]
52 public class EObjectInitializeBlock : Block
53 {
54 public const string type_name = "eobject_initialize";
55 internal EObjectWorkspace workspace_;
56
57 public EObjectInitializeBlock()
58 : base(type_name)
59 {
60 }
61
62 public void init()
63 {
64 this.appendDummyInput()
65 .appendField("初期化処理");
66 this.appendStatementInput("DO")
67 .setCheck(null);
68 this.setColour(230);
69 this.setTooltip("");
70 this.setHelpUrl("");
71 }
72
73 internal void OnCreate(EObjectWorkspace workspace, Create cre)
74 {
75 workspace_ = workspace;
76 }
77
78 internal void OnChange(EObjectWorkspace workspace, Change chg)
79 {
80 }
81
82 internal void OnDelete(EObjectWorkspace workspace, Delete del)
83 {
84 }
85
86 internal void OnMove(EObjectWorkspace workspace, Move mov)
87 {
88 }
89 }
90
91 public class EPropertyBlock : Block
92 {
93 internal JsonPropertyInfo PropertyInfo { get; private set; }
94 internal EObjectWorkspace Workspace { get; private set; }
95 public string Identifier { get; protected set; }
96 public string Description { get; protected set; }
97 public int PropertyCode { get; protected set; }
98 public int PropertySize { get; protected set; }
99
100 public EPropertyBlock(string type)
101 : base(type)
102 {
103 }
104
105 internal bool InitPropertyInfo(EObjectWorkspace workspace, bool initial = false)
106 {
107 var c = workspace.eobject;
108 PropertyInfo = null;
109 foreach (var pi in c.properties) {
110 if (pi.propertyCode != PropertyCode)
111 continue;
112
113 if (!initial && !App.BaseObjectPropertyList.Contains(pi))
114 continue;
115
116 PropertyInfo = pi;
117 Identifier = CodeGenerator.GetPropertyIdentifier(pi);
118 Description = pi.description;
119 PropertySize = ((pi.arrayCount == 0) ? 1 : pi.arrayCount) * pi.size;
120 break;
121 }
122
123 if (PropertyInfo == null) {
124 dispose(true);
125 return false;
126 }
127
128 return true;
129 }
130
131 internal void OnCreate(EObjectWorkspace workspace, Create cre)
132 {
133 Workspace = workspace;
134
135 if (PropertyInfo == null) {
136 if (!InitPropertyInfo(workspace, true))
137 return;
138 }
139
140 setFieldValue(PropertyCode.ToString("X2"), "PROPERTY_CODE");
141 setFieldValue(Identifier, "IDENTIFIER");
142 setFieldValue(Description, "DESCRIPTION");
143 setFieldValue(PropertySize.ToString(), "PROPERTY_SIZE");
144 }
145
146 internal void OnChange(EObjectWorkspace workspace, Change chg)
147 {
148 }
149
150 internal void OnDelete(EObjectWorkspace workspace, Delete del)
151 {
152 }
153
154 internal void OnMove(EObjectWorkspace workspace, Move mov)
155 {
156 }
157 }
158
159 public class EPropertyFixLenBlock : EPropertyBlock
160 {
161 public const string type_name = "eproperty_fixlen";
162 internal Tuple<string, string, string>[] cases_;
163 internal int defaultCount_;
164 internal bool userGetter_;
165 public Connection statementConnection_;
166 public Connection retvalConnection_;
167
168 public EPropertyFixLenBlock()
169 : base(type_name)
170 {
171 }
172
173 public void init()
174 {
175 setHelpUrl("http://www.example.com/");
176 setColour(230);
177 appendDummyInput("PROPERTY")
178 .appendField("EPC:")
179 .appendField("__", "PROPERTY_CODE")
180 .appendField("__", "DESCRIPTION")
181 .appendField("__", "IDENTIFIER")
182 .appendField("Size:")
183 .appendField("__", "PROPERTY_SIZE")
184 .appendField("byte");
185 setMutator(new Mutator(new[] {
186 EPropertyFixLenConstBlock.type_name,
187 EPropertyFixLenRangeBlock.type_name,
188 EPropertyFixLenDefaultBlock.type_name }));
189 setTooltip(new Func<string>(() => {
190 if ((cases_.Length == 0) && (defaultCount_ == 0)) {
191 return "条件に合うブロックを実行";
192 }
193 else if ((cases_.Length == 0) && (defaultCount_ != 0)) {
194 return "条件に合うブロックを実行、合うものがなければ最後のブロックを実行";
195 }
196 else if ((cases_.Length != 0) && (defaultCount_ == 0)) {
197 return "条件に合うブロックを実行";
198 }
199 else if ((cases_.Length != 0) && (defaultCount_ != 0)) {
200 return "条件に合うブロックを実行、合うものがなければ最後のブロックを実行";
201 }
202 return "";
203 }));
204 cases_ = new Tuple<string, string, string>[0];
205 defaultCount_ = 0;
206 userGetter_ = true;
207 updateSetter_();
208 updateGetter_(userGetter_);
209 }
210
211 /// <summary>
212 /// Create XML to represent the number of else-if and else inputs.
213 /// </summary>
214 /// <returns>XML storage element.</returns>
215 public Element mutationToDom(bool opt_caseIds)
216 {
217 if ((cases_.Length == 0) && (defaultCount_ == 0)) {
218 return null;
219 }
220 var container = Document.CreateElement("mutation");
221 for (var i = 0; i < cases_.Length; i++) {
222 var caseInfo = Document.CreateElement("case");
223 caseInfo.AppendChild(Document.CreateTextNode(cases_[i].Item1));
224 if (cases_[i].Item3 == null)
225 caseInfo.SetAttribute("value", cases_[i].Item2);
226 else {
227 caseInfo.SetAttribute("minimum", cases_[i].Item2);
228 caseInfo.SetAttribute("maximum", cases_[i].Item3);
229 }
230 container.AppendChild(caseInfo);
231 }
232 container.SetAttribute("default", defaultCount_.ToString());
233 container.SetAttribute("user_getter", userGetter_ ? "1" : "0");
234 container.SetAttribute("property_code", PropertyCode.ToString("X2"));
235 container.SetAttribute("identifier", Identifier);
236 container.SetAttribute("description", Description);
237 container.SetAttribute("property_size", PropertySize.ToString());
238 return container;
239 }
240
241 /// <summary>
242 /// Parse XML to restore the else-if and else inputs.
243 /// </summary>
244 /// <param name="xmlElement">XML storage element.</param>
245 public void domToMutation(Element xmlElement)
246 {
247 cases_ = new Tuple<string, string, string>[0];
248 Element childNode;
249 for (var i = 0; (childNode = (dynamic)xmlElement.ChildNodes[i]) != null; i++) {
250 if (childNode.NodeName.ToLower() == "case") {
251 var description = (childNode.ChildNodes.Length != 0) ? childNode.ChildNodes[0].NodeValue : "";
252 var value = childNode.GetAttribute("value");
253 if (value != null)
254 cases_.Push(new Tuple<string, string, string>(description, value, null));
255 else {
256 var min = childNode.GetAttribute("minimum");
257 var max = childNode.GetAttribute("maximum");
258 if ((min != null) && (max != null))
259 cases_.Push(new Tuple<string, string, string>(description, min, max));
260 }
261 }
262 }
263 var count = xmlElement.GetAttribute("default");
264 defaultCount_ = count == null ? 0 : Script.ParseInt(count, 10);
265 count = xmlElement.GetAttribute("user_getter");
266 userGetter_ = count == null ? false : (Script.ParseInt(count, 10) != 0);
267 count = xmlElement.GetAttribute("property_code");
268 PropertyCode = Script.ParseInt(count, 16);
269 if (Workspace != null)
270 InitPropertyInfo(Workspace, true);
271 Identifier = xmlElement.GetAttribute("identifier");
272 Description = xmlElement.GetAttribute("description");
273 count = xmlElement.GetAttribute("property_size");
274 PropertySize = count == null ? 0 : Script.ParseInt(count, 10);
275 updateSetter_();
276 updateGetter_(userGetter_);
277 }
278
279 /// <summary>
280 /// Populate the mutator's dialog with this block's components.
281 /// </summary>
282 /// <param name="workspace">Mutator's workspace.</param>
283 /// <returns>Root block in mutator.</returns>
284 public Block decompose(Workspace workspace)
285 {
286 var containerBlock = workspace.newBlock(EPropertyFixLenContainerBlock.type_name);
287 containerBlock.initSvg();
288 var connection = containerBlock.getInput("STACK").connection;
289 for (var i = 0; i < cases_.Length; i++) {
290 Block caseBlock;
291 var description = getFieldValue("CASE_DESCRIPTION" + i);
292 var value = getFieldValue("CASE_VALUE" + i);
293 if (value != null) {
294 caseBlock = workspace.newBlock(EPropertyFixLenConstBlock.type_name);
295 caseBlock.setFieldValue(description, "DESCRIPTION");
296 caseBlock.setFieldValue(value, "CONST");
297 }
298 else {
299 var min = getFieldValue("CASE_MIN" + i);
300 var max = getFieldValue("CASE_MAX" + i);
301 if ((min != null) && (max != null)) {
302 caseBlock = workspace.newBlock(EPropertyFixLenRangeBlock.type_name);
303 caseBlock.setFieldValue(description, "DESCRIPTION");
304 caseBlock.setFieldValue(min, "RANGE_MIN");
305 caseBlock.setFieldValue(max, "RANGE_MAX");
306 }
307 else
308 continue;
309 }
310 caseBlock.initSvg();
311 connection.connect(caseBlock.previousConnection);
312 connection = caseBlock.nextConnection;
313 }
314 if (defaultCount_ != 0) {
315 var defaultBlock = workspace.newBlock(EPropertyFixLenDefaultBlock.type_name);
316 defaultBlock.initSvg();
317 connection.connect(defaultBlock.previousConnection);
318 }
319 containerBlock.setFieldValue(this.userGetter_ ? "TRUE" : "FALSE", "USER_GETTER");
320 return containerBlock;
321 }
322
323 /// <summary>
324 /// Reconfigure this block based on the mutator dialog's components.
325 /// </summary>
326 /// <param name="containerBlock">Root block in mutator.</param>
327 public void compose(Block containerBlock)
328 {
329 var clauseBlock = containerBlock.getInputTargetBlock("STACK");
330 // Count number of inputs.
331 cases_ = new Tuple<string, string, string>[0];
332 defaultCount_ = 0;
333 var statementConnections = new Connection[0];
334 Connection defaultStatementConnection = null;
335 while (clauseBlock != null) {
336 switch (clauseBlock.type) {
337 case EPropertyFixLenConstBlock.type_name: {
338 var description = clauseBlock.getFieldValue("DESCRIPTION");
339 var value = clauseBlock.getFieldValue("CONST");
340 cases_.Push(new Tuple<string, string, string>(description, value, null));
341 statementConnections.Push(((EPropertyFixLenConstBlock)clauseBlock).statementConnection_);
342 }
343 break;
344 case EPropertyFixLenRangeBlock.type_name: {
345 var description = clauseBlock.getFieldValue("DESCRIPTION");
346 var range_min = clauseBlock.getFieldValue("RANGE_MIN");
347 var range_max = clauseBlock.getFieldValue("RANGE_MAX");
348 cases_.Push(new Tuple<string, string, string>(description, range_min, range_max));
349 statementConnections.Push(((EPropertyFixLenRangeBlock)clauseBlock).statementConnection_);
350 }
351 break;
352 case EPropertyFixLenDefaultBlock.type_name: {
353 defaultCount_++;
354 defaultStatementConnection = ((EPropertyFixLenDefaultBlock)clauseBlock).statementConnection_;
355 }
356 break;
357 default:
358 throw new Exception("Unknown block type.");
359 }
360 clauseBlock = (clauseBlock.nextConnection != null) ?
361 clauseBlock.nextConnection.targetBlock() : null;
362 }
363 updateSetter_();
364 // Reconnect any child blocks.
365 for (var i = 0; i <= cases_.Length; i++) {
366 Mutator.reconnect(statementConnections[i], this, "SET" + i);
367 }
368 Mutator.reconnect(defaultStatementConnection, this, "DEFAULT_SET");
369 var userGetter_ = containerBlock.getFieldValue("USER_GETTER");
370 if (userGetter_ != null) {
371 var userGetter = userGetter_ == "TRUE";
372 if (this.userGetter_ != userGetter) {
373 if (userGetter) {
374 updateGetter_(true);
375 // Restore the stack, if one was saved.
376 Mutator.reconnect(this.statementConnection_, this, "GET");
377 this.statementConnection_ = null;
378 Mutator.reconnect(this.retvalConnection_, this, "GET_RET");
379 this.retvalConnection_ = null;
380 }
381 else {
382 // Save the stack, then disconnect it.
383 var getterConnection = this.getInput("GET").connection;
384 this.statementConnection_ = getterConnection.targetConnection;
385 var getretConnection = this.getInput("GET_RET").connection;
386 this.retvalConnection_ = getretConnection.targetConnection;
387 if (this.statementConnection_ != null) {
388 var doBlock = getterConnection.targetBlock();
389 doBlock.unplug();
390 doBlock.bumpNeighbours_();
391 }
392 if (this.retvalConnection_ != null) {
393 var doBlock = getretConnection.targetBlock();
394 doBlock.unplug();
395 doBlock.bumpNeighbours_();
396 }
397 updateGetter_(false);
398 }
399 }
400 }
401 }
402
403 /// <summary>
404 /// Store pointers to any connected child blocks.
405 /// </summary>
406 /// <param name="containerBlock">Root block in mutator.</param>
407 public void saveConnections(Block containerBlock)
408 {
409 var clauseBlock = containerBlock.getInputTargetBlock("STACK");
410 var i = 0;
411 while (clauseBlock != null) {
412 switch (clauseBlock.type) {
413 case EPropertyFixLenConstBlock.type_name: {
414 var inputSet = getInput("SET" + i);
415 ((EPropertyFixLenConstBlock)clauseBlock).statementConnection_ =
416 (inputSet != null) ? inputSet.connection.targetConnection : null;
417 i++;
418 }
419 break;
420 case EPropertyFixLenRangeBlock.type_name: {
421 var inputSet = getInput("SET" + i);
422 ((EPropertyFixLenRangeBlock)clauseBlock).statementConnection_ =
423 (inputSet != null) ? inputSet.connection.targetConnection : null;
424 i++;
425 }
426 break;
427 case EPropertyFixLenDefaultBlock.type_name: {
428 var inputDo = getInput("DEFAULT_SET");
429 ((EPropertyFixLenDefaultBlock)clauseBlock).statementConnection_ =
430 (inputDo != null) ? inputDo.connection.targetConnection : null;
431 }
432 break;
433 default:
434 throw new Exception("Unknown block type.");
435 }
436
437 clauseBlock = (clauseBlock.nextConnection != null) ?
438 clauseBlock.nextConnection.targetBlock() : null;
439 }
440 var inputGet = getInput("GET");
441 statementConnection_ =
442 (inputGet != null) ? inputGet.connection.targetConnection : null;
443 var inputGetRet = getInput("GET_RET");
444 retvalConnection_ =
445 (inputGetRet != null) ? inputGetRet.connection.targetConnection : null;
446 }
447
448 /// <summary>
449 /// Modify this block to have the correct number of inputs.
450 /// </summary>
451 private void updateSetter_()
452 {
453 // Delete everything.
454 if (getInput("DEFAULT") != null) {
455 removeInput("DEFAULT");
456 removeInput("DEFAULT_SET");
457 }
458 var i = 0;
459 while (getInput("CASE" + i) != null) {
460 removeInput("CASE" + i);
461 removeInput("SET" + i);
462 i++;
463 }
464 // Rebuild block.
465 var getLabel = this.getInput("GET_LABEL");
466 i = 0;
467 foreach (var c in cases_) {
468 if (c.Item3 == null) {
469 appendDummyInput("CASE" + i)
470 .appendField("設定値が")
471 .appendField(c.Item1, "CASE_DESCRIPTION" + i)
472 .appendField(c.Item2, "CASE_VALUE" + i)
473 .appendField("の");
474 }
475 else {
476 appendDummyInput("CASE" + i)
477 .appendField("設定値が")
478 .appendField(c.Item1, "CASE_DESCRIPTION" + i)
479 .appendField(c.Item2, "CASE_MIN" + i)
480 .appendField("から")
481 .appendField(c.Item3, "CASE_MAX" + i)
482 .appendField("の");
483 }
484 if (getLabel != null) {
485 this.moveInputBefore("CASE" + i, "GET_LABEL");
486 }
487 appendStatementInput("SET" + i)
488 .appendField("とき");
489 if (getLabel != null) {
490 this.moveInputBefore("SET" + i, "GET_LABEL");
491 }
492 i++;
493 }
494 if (defaultCount_ != 0) {
495 if (cases_.Length == 0) {
496 appendDummyInput("DEFAULT")
497 .appendField("値が設定される");
498 }
499 else {
500 appendDummyInput("DEFAULT")
501 .appendField("設定値が不明の");
502 }
503 if (getLabel != null) {
504 this.moveInputBefore("DEFAULT", "GET_LABEL");
505 }
506 appendStatementInput("DEFAULT_SET")
507 .appendField("とき");
508 if (getLabel != null) {
509 this.moveInputBefore("DEFAULT_SET", "GET_LABEL");
510 }
511 }
512 }
513
514 private void updateGetter_(bool userGetter)
515 {
516 userGetter_ = userGetter;
517
518 if (getInput("GET") != null) {
519 removeInput("GET_LABEL");
520 removeInput("GET");
521 removeInput("GET_RET");
522 }
523 // Rebuild block.
524 if (userGetter_) {
525 appendDummyInput("GET_LABEL")
526 .appendField("値が取得される");
527 appendStatementInput("GET")
528 .appendField("とき");
529 appendValueInput("GET_RET")
530 .setCheck("String")
531 .setAlign(Blockly.ALIGN_RIGHT)
532 .appendField("返す値は");
533 }
534 }
535 }
536
537 public class EPropertyFixLenContainerBlock : Block
538 {
539 public const string type_name = "eproperty_fixlen_container";
540
541 public EPropertyFixLenContainerBlock()
542 : base(type_name)
543 {
544 }
545
546 public void init()
547 {
548 appendDummyInput()
549 .appendField("条件");
550 appendStatementInput("STACK");
551 // TODO:実行時に変更できない・・・(Dropdownでも×)
552 appendDummyInput("USER_GETTER_INPUT")
553 .appendField("取得時に保存してあるプロパティ値を返す。")
554 .appendField(new FieldCheckbox("TRUE"), "USER_GETTER");
555 setColour(230);
556 setTooltip("");
557 contextMenu = false;
558 }
559 }
560
561 [IgnoreCast]
562 public class EPropertyFixLenConstBlock : Block
563 {
564 public const string type_name = "eproperty_fixlen_const";
565 public Connection statementConnection_;
566
567 public EPropertyFixLenConstBlock()
568 : base(type_name)
569 {
570 }
571
572 public void init()
573 {
574 setColour(230);
575 appendDummyInput()
576 .appendField(new FieldTextInput("定数"), "DESCRIPTION")
577 .appendField(new FieldNumber("0", "-Infinity", "Infinity", 1), "CONST");
578 setPreviousStatement(true);
579 setNextStatement(true);
580 setTooltip("プロパティ値");
581 contextMenu = false;
582 }
583 }
584
585 public class EPropertyFixLenRangeBlock : Block
586 {
587 public const string type_name = "eproperty_fixlen_range";
588 public Connection statementConnection_;
589
590 public EPropertyFixLenRangeBlock()
591 : base(type_name)
592 {
593 }
594
595 public void init()
596 {
597 setColour(230);
598 appendDummyInput()
599 .appendField(new FieldTextInput("範囲"), "DESCRIPTION")
600 .appendField(new FieldNumber("0", "-Infinity", "Infinity", 1), "RANGE_MIN")
601 .appendField("から")
602 .appendField(new FieldNumber("255", "-Infinity", "Infinity", 1), "RANGE_MAX");
603 setPreviousStatement(true);
604 setNextStatement(true);
605 setTooltip("プロパティ値");
606 contextMenu = false;
607 }
608 }
609
610 public class EPropertyFixLenDefaultBlock : Block
611 {
612 public const string type_name = "eproperty_fixlen_default";
613 public Connection statementConnection_;
614
615 public EPropertyFixLenDefaultBlock()
616 : base(type_name)
617 {
618 }
619
620 public void init()
621 {
622 setColour(230);
623 appendDummyInput()
624 .appendField("その他");
625 setPreviousStatement(true);
626 setTooltip("不明なプロパティ値");
627 contextMenu = false;
628 }
629 }
630
631 public class EPropertyVarLenBlock : EPropertyBlock
632 {
633 public const string type_name = "eproperty_varlen";
634
635 public EPropertyVarLenBlock()
636 : base(type_name)
637 {
638 }
639
640 public void init()
641 {
642 this.appendDummyInput("PROPERTY")
643 .appendField("EPC:")
644 .appendField("__", "PROPERTY_CODE")
645 .appendField("__", "DESCRIPTION")
646 .appendField("__", "IDENTIFIER")
647 .appendField("Size:")
648 .appendField("__", "PROPERTY_SIZE")
649 .appendField("byte");
650 this.appendStatementInput("SET")
651 .setCheck("EPropertySetHandler")
652 .appendField("設定");
653 this.appendValueInput("SET_RET")
654 .setCheck("Number")
655 .setAlign(Blockly.ALIGN_RIGHT)
656 .appendField("設定に使用したバイト数");
657 this.appendStatementInput("GET")
658 .setCheck("EPropertyGetHandler")
659 .appendField("取得");
660 this.appendValueInput("GET_RET")
661 .setCheck("String")
662 .setAlign(Blockly.ALIGN_RIGHT)
663 .appendField("返すデータ");
664 this.setColour(230);
665 this.setTooltip("");
666 this.setHelpUrl("http://www.example.com/");
667
668 getField("PROPERTY_CODE").EDITABLE = true;
669 }
670 }
671
672 partial class Ruby
673 {
674 internal string defineENode(JsonNodeInfo enode, Workspace workspace)
675 {
676 var identifier = enode.identifier;
677
678 var nodes = new node[0];
679 var super = new colon2_node(this, new const_node(this, intern("ECNL")), intern("ENode"));
680 global = false;
681 var lv = local_switch();
682 {
683 var body = new begin_node(this, workspaceToNodes(workspace));
684 var cls = new class_node(this, intern(identifier), super, body);
685 nodes.Push(cls);
686 }
687 local_resume(lv);
688 global = true;
689
690 return finish(nodes);
691 }
692
693 internal string defineEObject(JsonObjectInfo eobject, Workspace workspace)
694 {
695 var identifier = eobject.identifier;
696
697 var nodes = new node[0];
698 var super = new colon2_node(this, new const_node(this, intern("ECNL")), intern("EObject"));
699 global = false;
700 var lv = local_switch();
701 {
702 var body = new begin_node(this, workspaceToNodes(workspace));
703 var cls = new class_node(this, intern(identifier), super, body);
704 nodes.Push(cls);
705 }
706 local_resume(lv);
707 global = true;
708
709 return finish(nodes);
710 }
711
712 public node enode_initialize(ENodeInitializeBlock block)
713 {
714 var workspace = block.workspace_;
715 var enode = workspace.eobject;
716 var properties = workspace.allEProperties(workspace.Workspace);
717
718 def_node def;
719 var lv = local_switch();
720 {
721 var fparams = new arg_node[] { new arg_node(this, local_add_f("eojx3")) };
722 var statements_do = statementToCode(block, "DO");
723
724 {
725 var eprpinib_table = new lvar_node(this, intern("eprpinib_table"));
726 var propinis = new node[0];
727 foreach (var pi in enode.properties) {
728 if (CodeGenerator.IsExtractProperty(pi))
729 continue;
730
731 var pb = properties.FirstOrDefault((i) => { return i.PropertyCode == pi.propertyCode; });
732
733 var ecnl_eproperty = new colon2_node(this, new const_node(this, intern("ECNL")), intern("EProperty"));
734 var args = new node[] {
735 new int_node(this, pi.propertyCode, 16),
736 getAccess(pi, pb),
737 getSize(pi, pb),
738 getExinf(pi, pb),
739 getSetter(pb),
740 getGetter(pb)
741 };
742 var propini = new call_node(this, ecnl_eproperty, intern("new"), args);
743
744 propinis.Push(propini);
745 }
746
747 var asgn = new asgn_node(this, eprpinib_table, new array_node(this, propinis, true));
748 statements_do.progs.Push(asgn);
749 }
750
751 {
752 var args = new node[] {
753 new lvar_node(this, intern("eojx3")),
754 new lvar_node(this, intern("eprpinib_table"))
755 };
756 var super = new super_node(this, args);
757 statements_do.progs.Push(super);
758 }
759
760 def = new def_node(this, intern("initialize"), fparams, statements_do);
761 }
762 local_resume(lv);
763 return def;
764 }
765
766 public node eobject_initialize(EObjectInitializeBlock block)
767 {
768 var workspace = block.workspace_;
769 var eobject = workspace.eobject;
770 var properties = workspace.allEProperties(workspace.Workspace);
771
772 def_node def;
773 var lv = local_switch();
774 {
775 var fparams = new arg_node[] {
776 new arg_node(this, local_add_f("eojx3")),
777 new arg_node(this, local_add_f("enod"))
778 };
779 var statements_do = statementToCode(block, "DO");
780
781 {
782 var eprpinib_table = new lvar_node(this, intern("eprpinib_table"));
783 var propinis = new node[0];
784 foreach (var pi in eobject.properties) {
785 if (CodeGenerator.IsExtractProperty(pi))
786 continue;
787
788 var pb = properties.FirstOrDefault((i) => { return i.PropertyCode == pi.propertyCode; });
789
790 var ecnl_eproperty = new colon2_node(this, new const_node(this, intern("ECNL")), intern("EProperty"));
791 var args = new node[] {
792 new int_node(this, pi.propertyCode, 16),
793 getAccess(pi, pb),
794 getSize(pi, pb),
795 getExinf(pi, pb),
796 getSetter(pb),
797 getGetter(pb)
798 };
799 var propini = new call_node(this, ecnl_eproperty, intern("new"), args);
800
801 propinis.Push(propini);
802 }
803
804 var asgn = new asgn_node(this, eprpinib_table, new array_node(this, propinis, true));
805 statements_do.progs.Push(asgn);
806 }
807
808 {
809 var args = new node[] {
810 new int_node(this, eobject.type.classGroup.classGroupCode, 16),
811 new int_node(this, eobject.type.classCode, 16),
812 new lvar_node(this, intern("eojx3")),
813 new lvar_node(this, intern("enod")),
814 new lvar_node(this, intern("eprpinib_table"))
815 };
816 var super = new super_node(this, args);
817 statements_do.progs.Push(super);
818 }
819
820 def = new def_node(this, intern("initialize"), fparams, statements_do);
821 }
822 local_resume(lv);
823 return def;
824 }
825
826 private node getSize(JsonPropertyInfo pi, EPropertyBlock pb)
827 {
828 if (pb != null)
829 pi = pb.PropertyInfo;
830 return new int_node(this, ((pi.arrayCount == 0) ? 1 : pi.arrayCount) * pi.size, 10);
831 }
832
833 private node getAccess(JsonPropertyInfo pi, EPropertyBlock pb)
834 {
835 if (pb != null)
836 pi = pb.PropertyInfo;
837 var list = new node[0];
838
839 if (pi.access.Contains("RULE_ANNO"))
840 list.Push(new colon2_node(this, new const_node(this, intern("ECNL")), intern("EPC_RULE_ANNO")));
841
842 if (pi.access.Contains("RULE_SET"))
843 list.Push(new colon2_node(this, new const_node(this, intern("ECNL")), intern("EPC_RULE_SET")));
844
845 if (pi.access.Contains("RULE_GET"))
846 list.Push(new colon2_node(this, new const_node(this, intern("ECNL")), intern("EPC_RULE_GET")));
847
848 if (pi.access.Contains("ANNOUNCE"))
849 list.Push(new colon2_node(this, new const_node(this, intern("ECNL")), intern("EPC_ANNOUNCE")));
850
851 if (pi.access.Contains("VARIABLE"))
852 list.Push(new colon2_node(this, new const_node(this, intern("ECNL")), intern("EPC_VARIABLE")));
853
854 switch (list.Length) {
855 case 0: return new colon2_node(this, new const_node(this, intern("ECNL")), intern("EPC_NONE"));
856 case 1: return list[0];
857 }
858
859 var or = intern("|");
860 call_node result = new call_node(this, list[0], or, list[1]);
861 for (int i = 2; i < list.Length; i++) {
862 result = new call_node(this, result, or, list[i]);
863 }
864 return result;
865 }
866
867 private node getExinf(JsonPropertyInfo pi, EPropertyBlock pb)
868 {
869 switch (pi.propertyCode) {
870 // 現在時刻設定
871 case 0x97:
872 // 現在年月日設定
873 case 0x98:
874 return new nil_node(this);
875 // その他
876 default:
877 if (pb == null)
878 return new sym_node(this, get_var_name(CodeGenerator.GetPropertyIdentifier(pi)));
879 return new sym_node(this, get_var_name(pb.Identifier));
880 }
881 }
882
883 private node getSetter(EPropertyBlock pb)
884 {
885 if (pb == null)
886 return new sym_node(this, intern("ecn_data_prop_set"));
887 return new sym_node(this, intern(pb.Identifier + "_set"));
888 }
889
890 private node getGetter(EPropertyBlock pb)
891 {
892 if (pb == null)
893 return new sym_node(this, intern("ecn_data_prop_get"));
894 return new sym_node(this, intern(pb.Identifier + "_get"));
895 }
896
897 public node eproperty_fixlen(EPropertyFixLenBlock block)
898 {
899 var text_identifier = block.Identifier;
900 var value_description = block.Description;
901 var value_property_code = block.PropertyCode.ToString("X2");
902 var value_property_size = block.PropertySize.ToString();
903
904 // 設定関数定義
905 def_node def_set;
906 var lv = local_switch();
907 {
908 var prop = local_add_f("prop");
909 var src = local_add_f("src");
910 var args = new arg_node[0];
911 args.Push(new arg_node(this, prop));
912 args.Push(new arg_node(this, src));
913
914 var statements_set = new begin_node(this, new node[0]);
915 {
916 var src_bytesize = new call_node(this, new lvar_node(this, src), intern("bytesize"));
917 var size = new int_node(this, Script.ParseInt(value_property_size));
918 var size_check_cond = new call_node(this, src_bytesize, intern("!="), size);
919 var size_check = new if_node(this, size_check_cond, new return_node(this, new int_node(this, 0)), null, false);
920 statements_set.progs.Push(size_check);
921 }
922
923 {
924 var anno_check_cond = new call_node(this, new lvar_node(this, prop), intern("anno"));
925 var prop_exinf = new call_node(this, new lvar_node(this, prop), intern("exinf"));
926 var set_anno_arg = new call_node(this, prop_exinf, intern("!="), new lvar_node(this, src));
927 var anno_check_then = new call_node(this, new lvar_node(this, prop), intern("set_anno"), new node[] { set_anno_arg });
928 var anno_check = new if_node(this, anno_check_cond, anno_check_then, null, false);
929 statements_set.progs.Push(anno_check);
930 }
931
932 var val = local_add_f("val");
933 {
934 node code;
935 var lsrc = new lvar_node(this, src);
936 var pos = new int_node(this, 0);
937 switch (value_property_size) {
938 case "1":
939 code = new call_node(this, lsrc, intern("getbyte"), new node[] { pos });
940 break;
941 case "2":
942 code = new fcall_node(this, intern("ecnl_getshort"), new node[] { lsrc, pos });
943 break;
944 case "4":
945 code = new fcall_node(this, intern("ecnl_getint"), new node[] { lsrc, pos });
946 break;
947 default:
948 code = new int_node(this, -1);
949 break;
950 }
951 code = new asgn_node(this, new lvar_node(this, val), code);
952 statements_set.progs.Push(code);
953 }
954
955 if (block.cases_.Length > 0) {
956 node argument0 = new lvar_node(this, val);
957 if (argument0 == null) argument0 = new int_node(this, -1);
958 var branches = new case_node.when_t[0];
959 for (var i = 0; i < block.cases_.Length; i++) {
960 var branch = statementToCode(block, "SET" + i);
961 var argument1 = block.getFieldValue("CASE_VALUE" + i);
962 if (argument1 != null) {
963 var when = new case_node.when_t() { body = branch };
964 when.value.Push(new int_node(this, argument1 == null ? 0 : Script.ParseInt(argument1, 10)));
965 branches.Push(when);
966 }
967 else {
968 var min = block.getFieldValue("CASE_MIN" + i);
969 var max = block.getFieldValue("CASE_MAX" + i);
970 if ((min != null) && (max != null)) {
971 var when = new case_node.when_t() { body = branch };
972 when.value.Push(new dot2_node(this,
973 new int_node(this, min == null ? 0 : Script.ParseInt(min, 10)),
974 new int_node(this, max == null ? 0 : Script.ParseInt(max, 10))));
975 branches.Push(when);
976 }
977 }
978 }
979 {
980 var branch = statementToCode(block, "DEFAULT_SET");
981 if (branch.progs.Length == 0) {
982 branch = new begin_node(this, new node[] { new return_node(this, new int_node(this, 0)) });
983 }
984 var when = new case_node.when_t() { body = branch };
985 branches.Push(when);
986 }
987
988 var code = new case_node(this, new lvar_node(this, val), branches);
989 statements_set.progs.Push(code);
990 }
991
992 var value_set_ret = new return_node(this, new int_node(this, Script.ParseInt(value_property_size)));
993 statements_set.progs.Push(value_set_ret);
994 def_set = new def_node(this, intern(text_identifier + "_set"), args, statements_set);
995 }
996 local_resume(lv);
997
998 // 取得関数定義
999 def_node def_get;
1000 lv = local_switch();
1001 {
1002 var prop = local_add_f("prop");
1003 var src = local_add_f("src");
1004 var args = new arg_node[0];
1005 args.Push(new arg_node(this, prop));
1006 args.Push(new arg_node(this, src));
1007
1008 var statements_get = statementToCode(block, "GET");
1009 var value_get_ret = valueToCode(block, "GET_RET");
1010 if (value_get_ret == null) {
1011 value_get_ret = new return_node(this, new str_node(this, ""));
1012 }
1013 statements_get.progs.Push(value_get_ret);
1014 def_get = new def_node(this, intern(text_identifier + "_get"), args, statements_get);
1015 }
1016 local_resume(lv);
1017
1018 // 設定関数定義と取得関数定義のリスト
1019 return node.cons(this, def_set, node.cons(this, def_get, null));
1020 }
1021
1022 public node eproperty_varlen(EPropertyVarLenBlock block)
1023 {
1024 var text_identifier = block.getFieldValue("IDENTIFIER");
1025 var value_description = block.getFieldValue("DESCRIPTION");
1026 var value_property_code = block.getFieldValue("PROPERTY_CODE");
1027 var value_property_size = block.getFieldValue("PROPERTY_SIZE");
1028
1029 // 設定関数定義
1030 def_node def_set;
1031 var lv = local_switch();
1032 {
1033 var prop = local_add_f("prop");
1034 var src = local_add_f("src");
1035 var args = new arg_node[0];
1036 args.Push(new arg_node(this, prop));
1037 args.Push(new arg_node(this, src));
1038
1039 var statements_set = statementToCode(block, "SET");
1040 var value_set_ret = valueToCode(block, "SET_RET");
1041 if (value_set_ret == null) {
1042 value_set_ret = new return_node(this, new int_node(this, 0));
1043 }
1044 statements_set.progs.Push(value_set_ret);
1045 def_set = new def_node(this, intern(text_identifier + "_set"), args, statements_set);
1046 }
1047 local_resume(lv);
1048
1049 // 取得関数定義
1050 def_node def_get;
1051 lv = local_switch();
1052 {
1053 var prop = local_add_f("prop");
1054 var src = local_add_f("src");
1055 var args = new arg_node[0];
1056 args.Push(new arg_node(this, prop));
1057 args.Push(new arg_node(this, src));
1058
1059 var statements_get = statementToCode(block, "GET");
1060 var value_get_ret = valueToCode(block, "GET_RET");
1061 if (value_get_ret == null) {
1062 value_get_ret = new return_node(this, new str_node(this, ""));
1063 }
1064 statements_get.progs.Push(value_get_ret);
1065 def_get = new def_node(this, intern(text_identifier + "_get"), args, statements_get);
1066 }
1067 local_resume(lv);
1068
1069 // 設定関数定義と取得関数定義のリスト
1070 return node.cons(this, def_set, node.cons(this, def_get, null));
1071 }
1072 }
1073}
Note: See TracBrowser for help on using the repository browser.