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

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

ファイルヘッダーコメントを追加

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