about summary refs log blame commit diff stats
path: root/file.lua
blob: 6b36b0f39e4af3399bde253ea448c693a7a4711d (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                                                      









                                               


                                                     
                                   





















                                                                                                                            

                                                      
                        
                                                      
     
                                      


                                  
                                    












                                                                             



                                                                 
                                                                             

                                          
                                                                             
                                          
                                                                                              
                                          
                           
                                                                         
                                                     

                                                             
                                    
                                                                                        
                                              

                                       


                       









                                          
                                             

                                                                                                           
                               
                                                                                              




                                                     
                               
                                      
                                                                                                                   
                                   
                                                                                                                                                                             

                                       


                       



                        




                             
                              


                              
                   
                                                                                                        



                                                           
        
                                 














                                                                             
                



















                                                                                              
                                              

                                       





                                       
                   
   
-- primitives for saving to file and loading from file
function file_exists(filename)
  local infile = App.open_for_reading(filename)
  if infile then
    infile:close()
    return true
  else
    return false
  end
end

function load_from_disk(State)
  local infile = App.open_for_reading(State.filename)
  State.lines = load_from_file(infile)
  if infile then infile:close() end
end

function load_from_file(infile)
  local result = {}
  if infile then
    local infile_next_line = infile:lines()  -- works with both Lua files and LÖVE Files (https://www.love2d.org/wiki/File)
    while true do
      local line = infile_next_line()
      if line == nil then break end
      if line == '```lines' then  -- inflexible with whitespace since these files are always autogenerated
        table.insert(result, load_drawing(infile_next_line))
      else
        table.insert(result, {mode='text', data=line})
      end
    end
  end
  if #result == 0 then
    table.insert(result, {mode='text', data=''})
  end
  return result
end

function save_to_disk(State)
  local outfile = App.open_for_writing(State.filename)
  if outfile == nil then
    error('failed to write to "'..State.filename..'"')
  end
  for _,line in ipairs(State.lines) do
    if line.mode == 'drawing' then
      store_drawing(outfile, line)
    else
      outfile:write(line.data, '\n')
    end
  end
  outfile:close()
end

json = require 'json'
function load_drawing(infile_next_line)
  local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}}
  while true do
    local line = infile_next_line()
    assert(line)
    if line == '```' then break end
    local shape = json.decode(line)
    if shape.mode == 'freehand' then
      -- no changes needed
    elseif shape.mode == 'line' or shape.mode == 'manhattan' then
      local name = shape.p1.name
      shape.p1 = Drawing.insert_point(drawing.points, shape.p1.x, shape.p1.y)
      drawing.points[shape.p1].name = name
      name = shape.p2.name
      shape.p2 = Drawing.insert_point(drawing.points, shape.p2.x, shape.p2.y)
      drawing.points[shape.p2].name = name
    elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then
      for i,p in ipairs(shape.vertices) do
        local name = p.name
        shape.vertices[i] = Drawing.insert_point(drawing.points, p.x,p.y)
        drawing.points[shape.vertices[i]].name = name
      end
    elseif shape.mode == 'circle' or shape.mode == 'arc' then
      local name = shape.center.name
      shape.center = Drawing.insert_point(drawing.points, shape.center.x,shape.center.y)
      drawing.points[shape.center].name = name
    elseif shape.mode == 'deleted' then
      -- ignore
    else
      print(shape.mode)
      assert(false)
    end
    table.insert(drawing.shapes, shape)
  end
  return drawing
end

function store_drawing(outfile, drawing)
  outfile:write('```lines\n')
  for _,shape in ipairs(drawing.shapes) do
    if shape.mode == 'freehand' then
      outfile:write(json.encode(shape), '\n')
    elseif shape.mode == 'line' or shape.mode == 'manhattan' then
      local line = json.encode({mode=shape.mode, p1=drawing.points[shape.p1], p2=drawing.points[shape.p2]})
      outfile:write(line, '\n')
    elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then
      local obj = {mode=shape.mode, vertices={}}
      for _,p in ipairs(shape.vertices) do
        table.insert(obj.vertices, drawing.points[p])
      end
      local line = json.encode(obj)
      outfile:write(line, '\n')
    elseif shape.mode == 'circle' then
      outfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius}), '\n')
    elseif shape.mode == 'arc' then
      outfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius, start_angle=shape.start_angle, end_angle=shape.end_angle}), '\n')
    elseif shape.mode == 'deleted' then
      -- ignore
    else
      print(shape.mode)
      assert(false)
    end
  end
  outfile:write('```\n')
end

-- for tests
function load_array(a)
  local result = {}
  local next_line = ipairs(a)
  local i,line,drawing = 0, ''
  while true do
    i,line = next_line(a, i)
    if i == nil then break end
--?     print(line)
    if line == '```lines' then  -- inflexible with whitespace since these files are always autogenerated
--?       print('inserting drawing')
      i, drawing = load_drawing_from_array(next_line, a, i)
--?       print('i now', i)
      table.insert(result, drawing)
    else
--?       print('inserting text')
      table.insert(result, {mode='text', data=line})
    end
  end
  if #result == 0 then
    table.insert(result, {mode='text', data=''})
  end
  return result
end

function load_drawing_from_array(iter, a, i)
  local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}}
  local line
  while true do
    i, line = iter(a, i)
    assert(i)
--?     print(i)
    if line == '```' then break end
    local shape = json.decode(line)
    if shape.mode == 'freehand' then
      -- no changes needed
    elseif shape.mode == 'line' or shape.mode == 'manhattan' then
      local name = shape.p1.name
      shape.p1 = Drawing.insert_point(drawing.points, shape.p1.x, shape.p1.y)
      drawing.points[shape.p1].name = name
      name = shape.p2.name
      shape.p2 = Drawing.insert_point(drawing.points, shape.p2.x, shape.p2.y)
      drawing.points[shape.p2].name = name
    elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then
      for i,p in ipairs(shape.vertices) do
        local name = p.name
        shape.vertices[i] = Drawing.insert_point(drawing.points, p.x,p.y)
        drawing.points[shape.vertices[i]].name = name
      end
    elseif shape.mode == 'circle' or shape.mode == 'arc' then
      local name = shape.center.name
      shape.center = Drawing.insert_point(drawing.points, shape.center.x,shape.center.y)
      drawing.points[shape.center].name = name
    elseif shape.mode == 'deleted' then
      -- ignore
    else
      print(shape.mode)
      assert(false)
    end
    table.insert(drawing.shapes, shape)
  end
  return i, drawing
end
/span>>0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> close<span class="Delimiter">(</span>server<span class="Delimiter">-&gt;</span>fd<span class="Delimiter">);</span> server<span class="Delimiter">-&gt;</span>fd = -<span class="Constant">1</span><span class="Delimiter">;</span> raise &lt;&lt; <span class="Constant">&quot;Failed to bind server socket to port &quot;</span> &lt;&lt; portno &lt;&lt; <span class="Constant">&quot;. Something's already using that port.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> listen<span class="Delimiter">(</span>server<span class="Delimiter">-&gt;</span>fd<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">queue length</span><span class="Comment">*/</span><span class="Constant">5</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _SOCKET<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$socket&quot;</span><span class="Delimiter">,</span> _SOCKET<span class="Delimiter">);</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> <span class="Normal">case</span> _SOCKET: <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'$socket' requires exactly one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of '$socket' should be a number, but got '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'$socket' requires exactly one product, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first product of '$socket' should be a number (file handle), but got '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> <span class="Normal">case</span> _SOCKET: <span class="Delimiter">{</span> <span class="Normal">int</span> port = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> socket_t* server = <span class="Normal">new</span> socket_t<span class="Delimiter">();</span> server_socket<span class="Delimiter">(</span>port<span class="Delimiter">,</span> server<span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>server<span class="Delimiter">-&gt;</span>fd &lt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">delete</span> server<span class="Delimiter">;</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> result = <span class="Normal">reinterpret_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>server<span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Normal">static_cast</span>&lt;<span class="Normal">double</span>&gt;<span class="Delimiter">(</span>result<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> session_socket<span class="Delimiter">(</span><span class="Normal">int</span> serverfd<span class="Delimiter">,</span> socket_t* session<span class="Delimiter">)</span> <span class="Delimiter">{</span> socklen_t dummy = <span class="Normal">sizeof</span><span class="Delimiter">(</span>session<span class="Delimiter">-&gt;</span>addr<span class="Delimiter">);</span> session<span class="Delimiter">-&gt;</span>fd = accept<span class="Delimiter">(</span>serverfd<span class="Delimiter">,</span> <span class="Delimiter">(</span><span class="Normal">struct</span> sockaddr*<span class="Delimiter">)</span>&amp;session<span class="Delimiter">-&gt;</span>addr<span class="Delimiter">,</span> &amp;dummy<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _ACCEPT<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$accept&quot;</span><span class="Delimiter">,</span> _ACCEPT<span class="Delimiter">);</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> <span class="Normal">case</span> _ACCEPT: <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'$accept' requires exactly one ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of '$accept' should be a number, but got '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'$accept' requires exactly one product, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first product of '$accept' should be a number (file handle), but got '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> <span class="Normal">case</span> _ACCEPT: <span class="Delimiter">{</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> socket_t* socket = <span class="Normal">reinterpret_cast</span>&lt;socket_t*&gt;<span class="Delimiter">(</span>x<span class="Delimiter">);</span> socket_t* session = <span class="Normal">new</span> socket_t<span class="Delimiter">();</span> session_socket<span class="Delimiter">(</span>socket<span class="Delimiter">-&gt;</span>fd<span class="Delimiter">,</span> session<span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> result = <span class="Normal">reinterpret_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>session<span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Normal">static_cast</span>&lt;<span class="Normal">double</span>&gt;<span class="Delimiter">(</span>result<span class="Delimiter">));</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _READ_FROM_SOCKET<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$read-from-socket&quot;</span><span class="Delimiter">,</span> _READ_FROM_SOCKET<span class="Delimiter">);</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> <span class="Normal">case</span> _READ_FROM_SOCKET: <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'$read-from-socket' requires exactly two ingredients, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of '$read-from-socket' should be a number, but got '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;second ingredient of '$read-from-socket' should be a number, but got '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'$read-from-socket' requires exactly two product, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> <span class="Normal">case</span> _READ_FROM_SOCKET: <span class="Delimiter">{</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Normal">int</span> bytes = <span class="Normal">static_cast</span>&lt;<span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="CommentedCode">//? Should this be something with more bytes?</span> socket_t* socket = <span class="Normal">reinterpret_cast</span>&lt;socket_t*&gt;<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Normal">int</span> socket_fd = socket<span class="Delimiter">-&gt;</span>fd<span class="Delimiter">;</span> <span class="Normal">char</span> contents[bytes]<span class="Delimiter">;</span> bzero<span class="Delimiter">(</span>contents<span class="Delimiter">,</span> bytes<span class="Delimiter">);</span> <span class="Normal">int</span> bytes_read = read<span class="Delimiter">(</span>socket_fd<span class="Delimiter">,</span> contents<span class="Delimiter">,</span> bytes - <span class="Constant">1</span> <span class="Comment">/*</span><span class="Comment"> null-terminated </span><span class="Comment">*/</span><span class="Delimiter">);</span> <span class="CommentedCode">//? cerr &lt;&lt; &quot;Read:\n&quot; &lt;&lt; string(contents) &lt;&lt; &quot;\n&quot;;</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>new_mu_text<span class="Delimiter">(</span>string<span class="Delimiter">(</span>contents<span class="Delimiter">)));</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>bytes_read<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _WRITE_TO_SOCKET<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$write-to-socket&quot;</span><span class="Delimiter">,</span> _WRITE_TO_SOCKET<span class="Delimiter">);</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> <span class="Normal">case</span> _WRITE_TO_SOCKET: <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'$write-to-socket' requires exactly two ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> <span class="Normal">case</span> _WRITE_TO_SOCKET: <span class="Delimiter">{</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> socket_t* session = <span class="Normal">reinterpret_cast</span>&lt;socket_t*&gt;<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Comment">// Write one character to a session at a time.</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> y = <span class="Normal">static_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Normal">char</span> c = <span class="Normal">static_cast</span>&lt;<span class="Normal">char</span>&gt;<span class="Delimiter">(</span>y<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>write<span class="Delimiter">(</span>session<span class="Delimiter">-&gt;</span>fd<span class="Delimiter">,</span> &amp;c<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> &lt;&lt; <span class="Constant">&quot;failed to write to socket</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> result = <span class="Normal">reinterpret_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>session<span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> _CLOSE_SOCKET<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">&quot;$close-socket&quot;</span><span class="Delimiter">,</span> _CLOSE_SOCKET<span class="Delimiter">);</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Checks&quot;)</span> <span class="Normal">case</span> _CLOSE_SOCKET: <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;'$close-socket' requires exactly two ingredient, but got '&quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>original_string &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise &lt;&lt; maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;first ingredient of '$close-socket' should be a character, but got '&quot;</span> &lt;&lt; to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> &lt;&lt; <span class="Constant">&quot;'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; end<span class="Delimiter">();</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> <span class="Normal">case</span> _CLOSE_SOCKET: <span class="Delimiter">{</span> <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span>&lt;<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>&gt;<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> socket_t* socket = <span class="Normal">reinterpret_cast</span>&lt;socket_t*&gt;<span class="Delimiter">(</span>x<span class="Delimiter">);</span> close<span class="Delimiter">(</span>socket<span class="Delimiter">-&gt;</span>fd<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> </pre> </body> </html> <!-- vim: set foldmethod=manual : -->