source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.3/Compiler/SymbolicExpressionTreeCompiler.cs @ 3747

Last change on this file since 3747 was 3747, checked in by gkronber, 11 years ago

Fixed bugs related to evaluation of ADFs in symbolic expressions. #791

File size: 4.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Linq;
24using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using System.Collections.Generic;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Symbols;
30
31namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Compiler {
32  public class SymbolicExpressionTreeCompiler {
33    private Dictionary<string, ushort> entryPoint = new Dictionary<string, ushort>();
34    private List<Func<Instruction, Instruction>> postInstructionCompiledHooks = new List<Func<Instruction, Instruction>>();
35
36    public Instruction[] Compile(SymbolicExpressionTree tree, Func<SymbolicExpressionTreeNode, byte> opCodeMapper) {
37      List<Instruction> code = new List<Instruction>();
38      entryPoint.Clear();
39      // compile main body
40      code.AddRange(Compile(tree.Root.SubTrees[0].SubTrees[0], opCodeMapper));
41      // compile branches
42      var functionBranches = from node in tree.IterateNodesPrefix()
43                             where node.Symbol is Defun
44                             select node;
45      foreach (DefunTreeNode branch in functionBranches) {
46        if (code.Count > ushort.MaxValue) throw new ArgumentException("Code for the tree is too long (> ushort.MaxValue).");
47        entryPoint[branch.FunctionName] = (ushort)code.Count;
48        code.AddRange(Compile(branch.SubTrees[0], opCodeMapper));
49      }
50      // address of all functions is fixed now
51      // iterate through code again and fill in the jump locations
52      for (int i = 0; i < code.Count; i++) {
53        Instruction instr = code[i];
54        if (instr.dynamicNode.Symbol is InvokeFunction) {
55          var invokeNode = (InvokeFunctionTreeNode)instr.dynamicNode;
56          instr.iArg0 = entryPoint[invokeNode.Symbol.FunctionName];
57          code[i] = instr;
58        }
59      }
60
61      return code.ToArray();
62    }
63
64    private IEnumerable<Instruction> Compile(SymbolicExpressionTreeNode branch, Func<SymbolicExpressionTreeNode, byte> opCodeMapper) {
65      foreach (var node in branch.IterateNodesPrefix()) {
66        Instruction instr = new Instruction();
67        if (node.SubTrees.Count > 255) throw new ArgumentException("Number of subtrees is too big (>255)");
68        instr.nArguments = (byte)node.SubTrees.Count;
69        instr.opCode = opCodeMapper(node);
70        if (node.Symbol is Argument) {
71          var argNode = (ArgumentTreeNode)node;
72          instr.iArg0 = (ushort)argNode.Symbol.ArgumentIndex;
73        }
74        instr.dynamicNode = node;
75        foreach (var hook in postInstructionCompiledHooks) {
76          instr = hook(instr);
77        }
78        yield return instr;
79      }
80    }
81
82    /// <summary>
83    /// Adds a function that will be called every time an instruction is compiled.
84    /// The compiled will insert the instruction returned by the hook into the code.
85    /// </summary>
86    /// <param name="hook">The hook that should be called for each compiled instruction.</param>
87    public void AddInstructionPostProcessingHook(Func<Instruction, Instruction> hook) {
88      postInstructionCompiledHooks.Add(hook);
89    }
90  }
91}
Note: See TracBrowser for help on using the repository browser.