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

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

Visual Studio 2019 と Bridge.NET でビルドできるよう更新。

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