start working on adding types

This commit is contained in:
CapsAdmin 2021-04-08 02:20:35 +02:00
parent 12d0d85727
commit 6f3c000bc0
4 changed files with 431 additions and 0 deletions

View File

@ -4,6 +4,7 @@
"tags" : [ "fun", "roleplay" ],
"ignore" :
[
"check.lua",
".gitignore",
".editorconfig",
".git*",

View File

@ -1,3 +1,28 @@
--[[#
import_type("nattlua/glua.nlua")
type pac = any
type VLL_CURR_FILE = false
type VLL2_FILEDEF = false
type function include(path: string)
local full_path = analyzer:ResolvePath("lua/" .. path:GetData())
local code_data = assert(require("nattlua").File(full_path))
assert(code_data:Lex())
assert(code_data:Parse())
local res = analyzer:AnalyzeRootStatement(code_data.SyntaxTree)
analyzer.loaded = analyzer.loaded or {}
analyzer.loaded[path] = res
return res
end
]]
-- VLL_CURR_FILE is local to each file
if CLIENT and pac and not VLL_CURR_FILE and not VLL2_FILEDEF then return end

80
nattlua.lua Normal file
View File

@ -0,0 +1,80 @@
package.path = '/home/caps/github/nattlua/?.lua;' .. package.path
local nl = require("nattlua")
local function GetFilesRecursively(dir, ext)
ext = ext or ".lua"
local f = assert(io.popen("find " .. dir))
local lines = f:read("*all")
local paths = {}
for line in lines:gmatch("(.-)\n") do
if line:sub(-4) == ext then
table.insert(paths, line)
end
end
return paths
end
local function read_file(path)
local f = assert(io.open(path, "r"))
local contents = f:read("*all")
f:close()
return contents
end
local function write_file(path, contents)
local f = assert(io.open(path, "w"))
f:write(contents)
f:close()
end
local function LintCodebase()
local lua_files = GetFilesRecursively("./lua/", ".lua")
local blacklist = {
["./lua/entities/gmod_wire_expression2/core/custom/pac.lua"] = true,
}
local config = {
preserve_whitespace = false,
string_quote = "\"",
no_semicolon = true,
force_parenthesis = true,
extra_indent = {
StartStorableVars = {
to = "EndStorableVars",
},
Start2D = {to = "End2D"},
Start3D = {to = "End3D"},
Start3D2D = {to = "End3D2D"},
-- in case it's localized
cam_Start2D = {to = "cam_End2D"},
cam_Start3D = {to = "cam_End3D"},
cam_Start3D2D = {to = "cam_End3D2D"},
cam_Start = {to = "cam_End"},
SetPropertyGroup = "toggle",
}
}
for _, path in ipairs(lua_files) do
if not blacklist[path] then
local lua_code = read_file(path)
local new_lua_code = assert(nl.Code(lua_code, "@" .. path, config)):Emit()
if new_lua_code:sub(#new_lua_code, #new_lua_code) ~= "\n" then
new_lua_code = new_lua_code .. "\n"
end
--assert(loadstring(new_lua_code, "@" .. path))
write_file(path, new_lua_code)
end
end
end
if false then LintCodebase() end
return {
main = "lua/autorun/pac_core_init.lua",
}

325
nattlua/glua.nlua Normal file
View File

@ -0,0 +1,325 @@
type Color = {
r = number,
g = number,
b = number,
a = number,
__index = self, -- __index = self is shortcut for type Color.__index = Color,
@MetaTable = self, -- shortcut for setmetatable<|Color, Color|>,
@Name = "Color",
}
type Vector = {
x = number,
y = number,
z = number,
}
type Angle = {
p = number,
y = number,
r = number,
__index = Angle,
__call = (function(self, number, number, number): Angle),
@MetaTable = self,
@Name = "Angle",
Right = (function(self): Vector), -- TODO: Vector():Angle():Right() seems to cause infinte loop if Right is not defined
}
local type ToScreenData = {
x = number,
y = number,
visible = boolean,
}
-- We can mutate the Vector type if we want
type Vector.__index = Vector
type Vector.__call = function(Vector, number, number, number): Vector
type Vector.__add = function(Vector, Vector): Vector
type Vector.__mul = function(number | Vector, number | Vector): Vector
type Vector.__unm = function(Vector): Vector
--type Vector.@Name = "Vector"
-- Or we can add a table:
type Vector = Vector & {
Zero = (function(self): nil),
WithinAABox = (function(self, boxStart: Vector, boxEnd: Vector): boolean),
ToScreen = (function(self): ToScreenData),
ToColor = (function(self): Color),
Sub = (function(self, vector: Vector): nil),
Set = (function(self, vector: Vector): nil),
Rotate = (function(self, rotation: Angle): nil),
Normalize = (function(self): nil),
Mul = (function(self, multiplier: number): nil),
LengthSqr = (function(self): number),
Length2DSqr = (function(self): number),
Length2D = (function(self): number),
Length = (function(self): number),
IsZero = (function(self): boolean),
IsEqualTol = (function(self, compare: Vector, tolerance: number): boolean),
GetNormalized = (function(self): Vector),
GetNormal = (function(self): Vector),
DotProduct = (function(self, Vector: Vector): number),
Dot = (function(self, otherVector: Vector): number),
Div = (function(self, divisor: number): nil),
DistToSqr = (function(self, otherVec: Vector): number),
Distance = (function(self, otherVector: Vector): number),
Cross = (function(self, otherVector: Vector): Vector),
AngleEx = (function(self, up: Vector): Angle),
Angle = (function(self): Angle),
Add = (function(self, vector: Vector): nil),
}
setmetatable<|Vector, Vector|>
-- because we can't easily forward declare types
-- we add a ToVector function here
type Color.ToVector = (function(Color): Vector),
local type BodyGroup = {
id = number,
name = string,
num = number,
submodels = {[number] = any} -- not sure what's in here
}
local type Matrix = {
GetTranslation = (function(self): Vector),
GetAngles = (function(self): Angle),
}
local type Triangle = {
color = Color,
normal = Vector,
binormal = Vector,
pos = Vector,
u = number,
v = number,
userdata = {number, number, number, number},
weights = {[number] = {
bone = number,
weight = number
}}
}
local type Mesh = {
Draw = (function(self): nil),
BuildFromTriangles = (function(self, {[number] = Triangle}): self),
@MetaTable = self,
__index = self,
__call = function(self, number, number, number): self
}
local type PhysicsObject = {
@Name = "PhysicsObject",
IsValid = (function(self): boolean),
}
local type EntityAttachments = {
[1 .. inf] = {
id = number,
name = string,
}
}
local type EntityAttachment = {
Ang = Angle,
Pos = Vector,
}
local type Entity = {
GetModel = (function(self): string),
SetAngles = (function(self, Angle): nil),
GetBodyGroups = (function(self, number): {[number] = BodyGroup}),
GetBodygroup = (function(self, number): number),
LookupSequence = (function(self, string): number),
ResetSequence = (function(self, number): nil),
SetCycle = (function(self, number): nil),
SetupBones = (function(self): nil),
TranslatePhysBoneToBone = (function(self, number): number),
TranslateBoneToPhysBone = (function(self, number): number),
GetBoneMatrix = (function(self, number): Matrix | nil),
GetChildBones = (function(self, number): {[number] = number}),
BoneLength = (function(self, number): number),
Remove = (function(self): nil),
GetBoneParent = (function(self): number),
GetBoneName = (function(self, number): string),
EyePos = (function(self): Vector),
EyeAngles = (function(self): Angle),
GetBoneCount = (function(self): number),
GetPos = (function(self): Vector),
IsStuck = (function(self): boolean),
GetAimVector = (function(self): Vector),
SetPos = (function(self, Vector): nil),
IsValid = (function(self): boolean),
GetPhysicsObject = (function(self): PhysicsObject),
GetVelocity = (function(self): Vector),
SetVelocity = (function(self, Vector): Vector),
GetAttachment = (function(self, number): EntityAttachment),
GetAttachments = (function(self): EntityAttachments),
}
type Entity.@Name = "Entity"
local type Player = Entity & {}
type Player.@Name = "Player"
type LocalPlayer = function(): Player
type timer = {
Simple = function(delay: number, callback: function(): nil): nil
}
type ClientsideModel = function(string): Entity
local type ModelMeshes = {
[number] = {
material = string,
triangles = {[number] = Triangle},
verticies = {[number] = Triangle},
}
}
type util = {}
type util.GetModelMeshes = (function(string, number, number): ModelMeshes)
local type WorldToLocal = (function(Vector, Angle, Vector, Angle): Vector, Angle)
local type hook = {}
local type Events = {
OnStart = (function(string, boolean): nil),
OnStop = (function(string, string, string): number)
}
type function hook.Add(eventName: string, obj: any, callback: (function(...): ...))
local event_callback = env.typesystem.Events:Get(eventName)
callback:SetReturnTypes(event_callback:GetReturnTypes())
callback:SetArguments(event_callback:GetArguments())
end
type function Entity:IsPlayer()
return types.Boolean()
end
type function CompileString(code: string, name: string, should_throw: boolean | nil)
should_throw = should_throw and should_throw:IsLiteral() and should_throw:GetData()
if should_throw == nil then should_throw = true end
code = code:IsLiteral() and code:GetData() or nil
name = name and name:IsLiteral() and name:GetData() or nil
if code then
local func, err = nl.load(code, name)
if func then
return func
end
if should_throw then
error(err)
end
return err
end
end
local type function isstring(obj: any)
local typ = analyzer:Call(env.typesystem.type, types.Tuple({obj}), analyzer.current_expression):Get(1)
return analyzer:BinaryOperator(analyzer.current_expression, typ, types.String("string"):SetLiteral(true), "runtime", "==")
end
local type function istable(obj: any)
local typ = analyzer:Call(env.typesystem.type, types.Tuple({obj}), analyzer.current_expression):Get(1)
return analyzer:BinaryOperator(analyzer.current_expression, typ, types.String("table"):SetLiteral(true), "runtime", "==")
end
local type function isentity(obj: any)
local Entity = env.typesystem.Entity
return analyzer:BinaryOperator(analyzer.current_expression, obj:GetMetaTable() or obj, Entity, "typesystem", "==")
end
type function table.Count(tbl: any): number
function string.Implode( seperator: literal string, Table: literal {[1 .. inf] = string} )
return table.concat( Table, seperator )
end
function string.GetFileFromFilename( path: literal string )
if ( !path:find( "\\" ) && !path:find( "/" ) ) then return path end
return path:match( "[\\/]([^/\\]+)$" ) or ""
end
function string.GetPathFromFilename( path: literal string )
return path:match( "^(.*[/\\])[^/\\]-$" ) or ""
end
function string.ToTable( str: literal string )
local tbl = {}
for i = 1, string.len( str ) do
tbl[i] = string.sub( str, i, i )
end
return tbl
end
function math.Clamp(low: literal number, n: literal number, high: literal number) return math.min(math.max(n, low), high) end
do
local totable = string.ToTable
local string_sub = string.sub
local string_find = string.find
local string_len = string.len
function string.Explode(separator: literal string, str: literal string, withpattern: literal boolean | nil)
if ( separator == "" ) then return totable( str ) end
if ( withpattern == nil ) then withpattern = false end
local ret = {}
local current_pos = 1
for i = 1, string_len( str ) do
local start_pos, end_pos = string_find( str, separator, current_pos, !withpattern )
if ( !start_pos ) then break end
ret[ i ] = string_sub( str, current_pos, start_pos - 1 )
current_pos = end_pos + 1
end
ret[ #ret + 1 ] = string_sub( str, current_pos )
return ret
end
function string.Split( str: literal string, delimiter: literal string )
return string.Explode( delimiter, str )
end
end
return {
hook = hook,
WorldToLocal = WorldToLocal,
Vector = Vector,
Angle = Angle,
Matrix = Matrix,
Player = Player,
util = util,
Mesh = Mesh,
ClientsideModel = ClientsideModel,
EntityAttachment = EntityAttachment,
EntityAttachments = EntityAttachments,
Entity = Entity,
istable = istable,
isentity = isentity,
isstring = isstring,
CompileString = CompileString,
}