]> git.lizzy.rs Git - metalua.git/commitdiff
improved match/types, started typecheck, misc.
authorFabien Fleutot <fabien@macfabien.local>
Fri, 29 Feb 2008 20:27:08 +0000 (21:27 +0100)
committerFabien Fleutot <fabien@macfabien.local>
Fri, 29 Feb 2008 20:27:08 +0000 (21:27 +0100)
src/lib/extension/match.mlua
src/lib/extension/types.mlua
src/samples/typecheck.mlua [new file with mode: 0644]
src/win32/relib.bat [new file with mode: 0644]

index 5b4c53ab3e0548c9048ac302a54aab0d8775c64e..0996c030370fbb22d5c3929c9889439aff5c99c3 100644 (file)
@@ -68,6 +68,8 @@
 ----------------------------------------------------------------------
 
 -- TODO: hygiene wrt type()
+-- TODO: cfg.ntmp isn't reset as often as it could. I'm not even sure
+--       the corresponding locals are declared.
 
 module ('spmatch', package.seeall)
 
@@ -122,6 +124,8 @@ function pattern_element_builder (pattern, term, cfg)
       id_pattern_element_builder (pattern, term, cfg)
    elseif "Op" == pattern.tag and "div" == pattern[1] then
       regexp_pattern_element_builder (pattern, term, cfg)
+   elseif "Op" == pattern.tag and "eq" == pattern[1] then
+      eq_pattern_element_builder (pattern, term, cfg)
    elseif "Table" == pattern.tag then
       table_pattern_element_builder (pattern, term, cfg)
    else 
@@ -129,6 +133,14 @@ function pattern_element_builder (pattern, term, cfg)
    end
 end
 
+function eq_pattern_element_builder (pattern, term, cfg)
+   local _, pat1, pat2 = unpack (pattern)
+   local ntmp_save = cfg.ntmp
+   pattern_element_builder (pat1, term, cfg)
+   cfg.ntmp = ntmp_save
+   pattern_element_builder (pat2, term, cfg)
+end
+
 -- pattern :: `Op{ 'div', string, list{`Id string} or `Id{ string }}
 -- term    :: expr
 function regexp_pattern_element_builder (pattern, term, cfg)
@@ -192,6 +204,7 @@ function table_pattern_element_builder (pattern, term, cfg)
          local v2 = next_tmpvar(cfg)
          acc_assign (v2, `Index{ term, key }, cfg)
          pattern_element_builder (sub_pattern, v2, cfg)
+         -- TODO: restore ntmp?
       end
    end
    if not seen_dots then -- Check arity
index 5c488310babbf4a660bae89c57955c8c0a5834f7..3d8bb5b3a24fb29cdefa2a102d0196f7e4bc57a5 100644 (file)
@@ -233,6 +233,10 @@ function process_type (type_term)
          | 'Op'     -> name = '__'..x[1]
          end
          x <- `Call{ `Index{ `Id "types", `String{ name } }, xcopy }
+      | `Function{ params, { results } } if results.tag=='Return' ->
+         results.tag = nil    
+         x <- `Call{ +{types.__function}, params, results }
+      | `Function{...} -> error "malformed function type"
       | _ -> -- pass
       end
    end
diff --git a/src/samples/typecheck.mlua b/src/samples/typecheck.mlua
new file mode 100644 (file)
index 0000000..631f672
--- /dev/null
@@ -0,0 +1,111 @@
+-- static partial checkings for Lua.\r
+--\r
+-- This program checks some metalua or plain lua source code for most common\r
+-- mistakes. Its design focuses on the ability to check plain lua code: there is\r
+-- no need to load any extension in the module.\r
+--\r
+-- The current checkings include:\r
+--\r
+-- * Listing all free variables, and make sure they are declared.\r
+-- * For free vars known as modules, check that indexings in them are also\r
+--   declared.\r
+-- * When the type of something is known, do some basic type checkings. These\r
+--   checkings are by no means exhaustive; however, when a parameter function\r
+--   is constant or statically declared, it's checked.\r
+\r
+\r
+\r
+--[[\r
+Type grammar:\r
+\r
+t ::=\r
+| t and t\r
+| t or  t\r
+| function (t, ...) return t, ... end\r
+| { (k=t)... }\r
+| table(t, t)\r
+| string\r
+| number\r
+| integer\r
+| boolean\r
+| userdata\r
+| nil\r
+| multi(t, ...)\r
+| _\r
+\r
+--]]\r
+\r
+\r
+match function get_type\r
+| `Number{...} -> return +{number}\r
+| `String{...} -> return +{string}\r
+| `True|`False -> return +{boolean}\r
+| `Nil         -> return +{nil}\r
+| `Dots        -> return +{_}\r
+| `Stat{_,v}   -> return get_type(v)\r
+| `Paren{t}    -> return get_one_type(t)\r
+| `Call{f, ...} -> \r
+   local ftype = get_type(f)\r
+   match ftype with\r
+   | `Function{ _, {`Return{result}} } -> return get_type(result)\r
+   | `Function{ _, {`Return{...} == results} } ->\r
+      local r2 = +{ multi() }\r
+      for r in ivalues(results) table.insert(r2, get_type(r)) end\r
+      return r2\r
+   | `And{...} -> return +{_} -- not implemented\r
+   | `Or{ a, b } -> match get_one_type(a), get_one_type(b) with\r
+     | `Function{...}==f1, `Function{...}==f2 ->\r
+       return `Op{ 'or', get_type(`Call{f1}), get_type(`Call{f2})}\r
+     | `Function{...}==f, _ | _, `Function{...}==f ->\r
+       return get_type(`Call{f})\r
+   | _ -> return +{_}\r
+   end\r
+| `Invoke{o, m, ... } ==  x -> return get_type(`Call{`Index{o, m}})\r
+| `Op{...}==o -> return get_op_type(o)\r
+| `Table{...}==t ->\r
+   local r = `Table{ }\r
+   for x in ivalues(t) do\r
+      match x with\r
+      | `Pair{ `String{...}==k, v } -> table.insert(r, `Pair{k, get_one_type(v)})\r
+      | t -> table.insert(r, get_one_type(t))\r
+      end\r
+   end\r
+   return r\r
+| `Function{...}==f ->\r
+| `Id{v} ->\r
+| `Index{t, k} -> match get_one_type(t), get_one_type(k) with\r
+   | `Call{`Id 'table', tk, tv }, _ -> return tv\r
+   | `Table{...}==tt, `Id 'string' ->\r
+\r
+\r
+\r
+local types_rt = require 'extension.types'\r
+\r
+\r
+\r
+\r
+function check_function(f, term)\r
+   match get_type(term) with\r
+   | `Function{ params, {`Return{...} == results}}, args ->\r
+   | `And{ a, b }, args ->\r
+      check_function(a, args)\r
+      check_function(b, args)\r
+   | `Or{ a, b }, args ->\r
+      if not pcall(check_function, a, args) then check_function(b, args) end\r
+   | `Id '_' -> -- pass\r
+   | _ -> error ("Call to a non-function")\r
+   end\r
+end\r
+\r
+function check_index(a, b, term)\r
+   match get_type(term) with\r
+   | `Table{}\r
+\r
+match function cfg.id.up\r
+| `Call{ f, ... } == x -> check_function (f, x)\r
+| `Index{ a, b }  == x -> check_index (a, b, x)\r
+end   \r
+\r
+\r
+-- List free vars\r
+cfg.id.
\ No newline at end of file
diff --git a/src/win32/relib.bat b/src/win32/relib.bat
new file mode 100644 (file)
index 0000000..3160e93
--- /dev/null
@@ -0,0 +1,3 @@
+set MLUALIB_TARGET=d:\tmp\mlualib\r
+xcopy /E /Y lib %MLUALIB_TARGET%\r
+lua win32\precompile.lua %MLUALIB_TARGET%\r