Re: Architectural Discussion: Implementing ECS and Data-Oriented Programming (DOP)

new topic     » goto parent     » topic index » view thread      » older message » newer message

Here is the class library:

namespace classes 
-- classes.e 
-- do not modify this file 
 
------------------------------------------------------------------------------ 
-- INTERNAL CONSTANTS 
------------------------------------------------------------------------------ 
 
constant CLASS_NAME   =1, CLASS_PROPERTY=2,   CLASS_METHOD=3 
constant PROPERTY_NAME=1, PROPERTY_VALUE=2 
constant METHOD_NAME  =1, METHOD_ROUTINE_ID=2 
constant ENTITY_CLASS =1, ENTITY_VALUES=2 
 
------------------------------------------------------------------------------ 
-- GLOBAL CLASS FUNCTIONS 
------------------------------------------------------------------------------ 
 
-- define a Class 
public function class(sequence className) 
  return {className, {}, {}} 
end function 
 
------------------------------------------------------------------------------ 
 
-- define a Class property 
public function addProperty(sequence class, sequence propertyName, object defaultValue) 
  class[CLASS_PROPERTY] = append(class[CLASS_PROPERTY], {propertyName, defaultValue}) 
  return class 
end function 
 
------------------------------------------------------------------------------ 
 
-- define a Class method 
public function addMethod(sequence class, sequence methodName, integer routineId) 
  class[CLASS_METHOD] = append(class[CLASS_METHOD], {methodName, routineId}) 
  return class 
end function 
 
------------------------------------------------------------------------------ 
 
-- find property 
public function findProperty(sequence class, sequence property) 
  for i = 1 to length(class[CLASS_PROPERTY]) do 
    if equal(property, class[CLASS_PROPERTY][i][PROPERTY_NAME]) then 
      return i 
    end if 
  end for 
  return 0 
end function 
 
------------------------------------------------------------------------------ 
 
-- find method routine_id 
public function findMethod(sequence class, sequence method) 
  for i = 1 to length(class[CLASS_METHOD]) do 
    if equal(method, class[CLASS_METHOD][i][METHOD_NAME]) then 
      return class[CLASS_METHOD][i][METHOD_ROUTINE_ID] 
    end if 
  end for 
  return 0 
end function 
 
------------------------------------------------------------------------------ 
-- GLOBAL ENTITY FUNCTIONS 
------------------------------------------------------------------------------ 
 
-- create an Entity of the class 
public function new(sequence class) 
  sequence values =  {} 
  for i = 1 to length(class[CLASS_PROPERTY]) do 
    values = append(values, class[CLASS_PROPERTY][i][PROPERTY_VALUE]) 
  end for 
  return {class, values} 
end function 
 
------------------------------------------------------------------------------ 
 
-- get property value 
public function getProperty(sequence entity, sequence property, object defaultValue=0) 
  integer propertyID = findProperty(entity[ENTITY_CLASS], property) 
  if propertyID then 
    return entity[ENTITY_VALUES][propertyID] 
  end if 
  return defaultValue 
end function 
 
------------------------------------------------------------------------------ 
 
-- set property value 
public function setProperty(sequence entity, sequence property, object val) 
  integer propertyID = findProperty(entity[ENTITY_CLASS], property) 
  if propertyID then 
    entity[ENTITY_VALUES][propertyID] = val 
  end if 
  return entity 
end function 
 
------------------------------------------------------------------------------ 
 
-- call a method (function) within an Entity 
public function callMethod(sequence entity, sequence method, object methodParams= {}) 
  integer methodID = findMethod(entity[ENTITY_CLASS], method) 
  if methodID then 
    return call_func(methodID, {entity, methodParams}) 
  end if 
  return -1 
end function 

And an outdated version of the preprocessor that I began to update but I did not finish the job because noone was interested in.

include std/io.e 
include std/text.e 
include std/regex.e 
include std/search.e 
include std/sequence.e 
include std/datetime.e 
include std/console.e 
include common.e 
 
constant ATTR=1, PROC=2, FUNC=3 
 
------------------------------------------------------------------------------ 
 
function get_next_non_white(sequence code, integer from) 
  -- skip white 
  while (code[from] = ' ') or (code[from] = '\t') do 
    from += 1 
    if from > length(code) then return 0 end if 
  end while 
  return from 
end function 
 
------------------------------------------------------------------------------ 
 
function manage_routine(sequence code, sequence lines, integer start) 
  integer from, upto 
   
  for i = start+1 to length(lines) do 
    if begins("end ", trim(lines[i])) then 
      code &= lines[i] & "\n" 
      start = i 
      exit 
    end if 
    sequence rule = "self\\.([_A-Za-z][_A-Za-z0-9]*)" 
    -- puts(f_out, rule & "\n") 
    regex r = regex:new(rule) 
    object found = regex:find_all(r, lines[i]) 
    if sequence(found) then 
      for j = 1 to length(found) do 
        {from, upto} = found[j][2] 
        sequence name = lines[i][from..upto] 
        {from, upto} = found[j][1] 
        lines[i] = replace(lines[i], sprintf("entity[%s]", {upper(name)}), from, upto) 
      end for 
      code &= lines[i] & "\n" 
      puts(f_debug, lines[i] & "\n") 
    end if 
  end for 
  return {code, start} 
end function 
 
------------------------------------------------------------------------------ 
 
procedure main(sequence cmd) 
  f_debug = open(InitialDir & "debug.log", "w") 
  debug_level = DEBUG 
  debug_time_stamp = 0 
 
  sequence inFileName, outFileName 
   
  for i = 3 to length(cmd) do 
    switch cmd[i] do 
      case "-i" then 
        inFileName = cmd[i+1] 
      case "-o" then 
        outFileName = cmd[i+1] 
    end switch 
  end for 
 
  integer f_out = open(outFileName, "w") 
  sequence lines = read_lines(inFileName) 
  integer from, upto 
  object found, found2 
  sequence class_name = "", name, params, elements = {} 
  integer start = 0 
   
  sequence code = "" 
   
  -- find class definition 
  regex r = regex:new("class (.*)$") 
  for i = 1 to length(lines) do 
    puts(f_debug, lines[i] & "\n") 
    found = regex:find(r, lines[i]) 
    if sequence(found) then 
      {from, upto} = found[2] 
      class_name = lines[i][from..upto] 
      start = i 
      exit 
    else 
      code &= lines[i] & "\n" 
    end if 
  end for 
   
  -- add target sequence attributes 
  code &= "enum type %ENUM_TYPE% %ENUM_ITEMS% end type\n\n" 
  code &= "sequence %CLASS_NAME% = {%CLASS_CONTENT%}\n\n" 
   
  -- analyze class definition 
  sequence enums = {} 
  sequence class_definition = {} 
  integer i = start+1 
  while i <= length(lines) do 
    sequence trimmed = trim(lines[i]) 
    puts(f_debug, lines[i] & "\n") 
    if match("end class", lines[i]) then 
      start = i 
      exit 
    end if 
    if begins("integer", trimmed) then 
      r = regex:new("integer (.*)$") 
      class_definition= append(class_definition, "0") 
      found = regex:find(r, lines[i]) 
      {from, upto} = found[2] 
      name = lines[i][from..upto] 
      enums = append(enums, upper(name)) 
      elements = append(elements, {name, ATTR}) 
    elsif begins("atom", trimmed) then 
      r = regex:new("atom (.*)$") 
      class_definition= append(class_definition, "0.0") 
      found = regex:find(r, lines[i]) 
      {from, upto} = found[2] 
      name = lines[i][from..upto] 
      enums = append(enums, upper(name)) 
      elements = append(elements, {name, ATTR}) 
    elsif begins("sequence", trimmed) then 
      r = regex:new("sequence (.*)$") 
      class_definition= append(class_definition, "\"\"") 
      found = regex:find(r, lines[i]) 
      {from, upto} = found[2] 
      name = lines[i][from..upto] 
      enums = append(enums, upper(name)) 
      elements = append(elements, {name, ATTR}) 
    elsif begins("object", trimmed) then 
      r = regex:new("object (.*)$") 
      class_definition= append(class_definition, "0") 
      found = regex:find(r, lines[i]) 
      {from, upto} = found[2] 
      name = lines[i][from..upto] 
      enums = append(enums, upper(name)) 
      elements = append(elements, {name, ATTR}) 
    elsif begins("datetime", trimmed) then 
      r = regex:new("datetime (.*)$") 
      class_definition= append(class_definition, "now()") 
      found = regex:find(r, lines[i]) 
      {from, upto} = found[2] 
      name = lines[i][from..upto] 
      enums = append(enums, upper(name)) 
      elements = append(elements, {name, ATTR}) 
    elsif begins("procedure", trimmed) then 
      r = regex:new("procedure (.*)\\((.*)\\)$") 
      found = regex:find(r, lines[i]) 
      {from, upto} = found[2] 
      name = lines[i][from..upto] 
      enums = append(enums, upper(name)) 
      {from, upto} = found[3] 
      params = lines[i][from..upto] 
      code &= sprintf("procedure %s(sequence entity, sequence params)\n", {name}) 
      {code, i} = manage_routine(code, lines, i) 
      elements = append(elements, {name, PROC}) 
    elsif begins("function", trimmed) then 
      r = regex:new("function (.*)\\((.*)\\)$") 
      found = regex:find(r, lines[i]) 
      {from, upto} = found[2] 
      name = lines[i][from..upto] 
      enums = append(enums, upper(name)) 
      {from, upto} = found[3] 
      params = lines[i][from..upto] 
      code &= sprintf("function %s(sequence entity, sequence params)\n", {name}) 
      {code, i} = manage_routine(code, lines, i) 
      elements = append(elements, {name, FUNC}) 
    elsif begins("end procedure", trimmed) then 
      class_definition= append(class_definition, "0") 
      code &= lines[i] & "\n" 
      code &= sprintf("%s[%s] = routine_id(\"%s\")\n", {class_name, upper(name), name}) 
    elsif begins("end function", trimmed) then 
      class_definition= append(class_definition, "0") 
      code &= lines[i] & "\n" 
      code &= sprintf("%s[%s] = routine_id(\"%s\")\n", {class_name, upper(name), name}) 
    else 
      common:error_message("Unexpected variable type!", 1) 
    end if 
    i += 1 
  end while 
  analyze_object(class_definition, class_name, DEBUG) 
  analyze_object(enums, "enums", DEBUG) 
   
  -- replace target sequence attributes 
  code = replace_all(code, "%ENUM_TYPE%", upper(class_name)) 
  code = replace_all(code, "%ENUM_ITEMS%", join(enums, ',')) 
  code = replace_all(code, "%CLASS_NAME%", class_name) 
  code = replace_all(code, "%CLASS_CONTENT%", join(class_definition, ',')) 
   
  -- add converted code 
  puts(f_out, code) 
   
  -- add internal functions 
  puts(f_out, "\n") 
  puts(f_out, "procedure class_proc(sequence entity, integer method, sequence params = {})\n") 
  puts(f_out, "  call_proc(entity[method], {entity, params})\n") 
  puts(f_out, "end procedure\n") 
  puts(f_out, "\n") 
   
  puts(f_out, "function class_func(sequence entity, integer method, sequence params = {})\n") 
  puts(f_out, "  return call_func(entity[method], {entity, params})\n") 
  puts(f_out, "end function\n") 
  puts(f_out, "\n") 
   
  -- manage class entities 
  sequence entity_name = "" 
  sequence entities = "" 
  for l = start+1 to length(lines) do 
    -- lines[l] = trim(lines[l]) 
    puts(f_debug, lines[l] & "\n") 
    sequence rule = sprintf("sequence (.*) = new\\(%s\\)$", {class_name}) 
    -- puts(f_out, rule & "\n") 
    r = regex:new(rule) 
    found = regex:find(r, lines[l]) 
    if sequence(found) then 
      {from, upto} = found[2] 
      entity_name = lines[l][from..upto] 
      entities = append(entities, entity_name) 
      printf(f_out, "sequence %s = %s\n", {entity_name, class_name}) 
    else 
      r = regex:new("([_A-Za-z0-9]*)\\.([_A-Za-z0-9]*)") 
      found = regex:find(r, lines[l]) 
      if sequence(found) then 
        {from, upto} = found[2] 
        entity_name = lines[l][from..upto] 
        if find(entity_name, entities) then  -- class referenced 
          -- check if it refers to a routine 
          {from, upto} = found[3] 
          name = lines[l][from..upto] 
          {from, upto} = found[1] 
          integer p = vlookup(name, elements, 1, 2, 0) 
          printf(f_debug, "p = %d\n", {p}) 
          switch p do 
            case ATTR then 
              lines[l] = replace(lines[l], sprintf("%s[%s]", {entity_name, upper(name)}), from, upto) 
            case PROC then 
              from = find('(', lines[l], upto+1) 
              upto = find(')', lines[l], upto+1) 
              if upto > from+1 then 
                params = lines[l][from+1..upto-1] 
              else 
                params = {} 
              end if 
              lines[l] = sprintf("class_proc(%s, %s, %s)\n", {entity_name, upper(name), params}) 
            case FUNC then 
              from = find('(', lines[l], upto+1) 
              upto = find(')', lines[l], upto+1) 
              if upto > from+1 then 
                params = lines[l][from+1..upto-1] 
              else 
                params = {} 
              end if 
              lines[l] = sprintf("class_proc(%s, %s, %s)\n", {entity_name, upper(name), params}) 
            case else 
          end switch 
        end if 
      end if 
      puts(f_out, lines[l] & "\n") 
    end if 
  end for 
  analyze_object(entities, "entities", DEBUG) 
   
  close(f_out) 
  close(f_debug) 
end procedure  -- main 
 
------------------------------------------------------------------------------ 
 
-- Main 
main(command_line()) 
maybe_any_key() 

As it was a work in progress, I'm not sure it runs again without modifications.

Jean-Marc

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu