Skip to content

Commit

Permalink
Merge pull request #25 from 1Axen/generics-rework
Browse files Browse the repository at this point in the history
Internals refactoring
  • Loading branch information
1Axen authored Oct 25, 2024
2 parents d552e79 + e0ecb1d commit a641169
Show file tree
Hide file tree
Showing 12 changed files with 1,321 additions and 742 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"luau-lsp.plugin.enabled": true,
"luau-lsp.require.mode": "relativeToFile",
"luau-lsp.require.directoryAliases": {
"@lune/": "~/.lune/.typedefs/0.8.7/"
"@lune/": "~/.lune/.typedefs/0.8.9/"
},
"luau-lsp.sourcemap.rojoProjectFile": "default.project.json"
}
2 changes: 1 addition & 1 deletion rokit.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

[tools]
selene = "Kampfkarren/selene@0.26.1"
lune = "filiptibell/lune@0.8.7"
lune = "filiptibell/lune@0.8.9"
darklua = "seaofvoices/darklua@0.13.1"
rojo = "rojo-rbx/rojo@7.4.1"
run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0"
41 changes: 3 additions & 38 deletions src/Generator/Prefabs.luau
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ local Parser = require("../Parser")
type Block = Blocks.Block
type Writer = (Value: string, Block: Block, Range: NumberRange?, Components: {string}?) -> ()
type Reader = (Variable: string, Block: Block, Range: NumberRange?, Components: {string}?) -> ()
type Generate = (Declaration: Parser.PrimitiveDeclaration, Variable: string?, Read: Block, Write: Block, WriteValidations: boolean?) -> ()
type Generate = (Declaration: Parser.Primitive, Variable: string?, Read: Block, Write: Block, WriteValidations: boolean?) -> ()

type TypePrefab = {
Read: Reader,
Expand Down Expand Up @@ -79,7 +79,7 @@ local Structures = {
Array = nil :: any
}
local Primitives: {[string]: {
Type: string | (Declaration: Parser.PrimitiveDeclaration) -> string,
Type: string | (Declaration: Parser.Primitive) -> string,
Generate: Generate
}} = {}

Expand Down Expand Up @@ -110,7 +110,7 @@ local function GetTypeToUseByBits(UpperBits: number): TypePrefab
end

local function GeneratePrimitivePrefab(Type: string, Prefab: TypePrefab, AssertGenerator: AssertGenerator?): Generate
return function(Declaration: Parser.PrimitiveDeclaration, Variable: string?, Read: Block, Write: Block, WriteValidations: boolean?)
return function(Declaration: Parser.Primitive, Variable: string?, Read: Block, Write: Block, WriteValidations: boolean?)
local Value = Declaration.Value
local Tokens = Declaration.Tokens
local Variable = Variable or "Value"
Expand Down Expand Up @@ -258,41 +258,6 @@ Primitives.f16 = {
Generate = GeneratePrimitivePrefab("number", Types.f16, Asserts.number)
}

--> Structures
Structures.Array = function(Variable: string, Read: Block, Write: Block, Bounds: NumberRange, Iterator: string?): (Block, Block)
local Lower = Bounds.Min
local Upper = Bounds.Max
local ReadArray, WriteArray;

local Iterator = Iterator or "Item"
local IsVariableSize = (Lower ~= Upper)

--> Length
if IsVariableSize then
local LengthType = GetTypeToUse(Upper)
LengthType.Read("Length", Read)
local Assert = Asserts.number("Length", Lower, Upper)

Read:Line(Assert.Lower)
Read:Line(Assert.Upper)
LengthType.Write(`#{Variable}`, Write)
else
Read:Line(`local Length = {Upper}`)
end

--> Array
Read:Line(`{Read:Declare(Variable)} = table.create(Length)`)

--> Body
ReadArray = Read:Loop("Index = 1", "Length")
WriteArray = Write:Loop("Index = 1", IsVariableSize and `#{Variable}` or Upper)

--ReadArray:Line(Read:Declare(Iterator))
WriteArray:Line(`local {Iterator} = {Variable}[Index]`)

return ReadArray, WriteArray
end

--> Boolean
do
Types.boolean = {
Expand Down
85 changes: 37 additions & 48 deletions src/Generator/Typescript.luau
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
--!strict

local Parser = require("../Parser")
local Settings = require("../Settings")

Expand All @@ -7,7 +9,7 @@ local Prefabs = require("./Prefabs")

local Builder = require("../Modules/Builder")

type Type = Parser.TypeDeclaration
type Type = Parser.TypeNode
type Scope = Parser.Scope
type Context = "Client" | "Server" | "Shared"
type AbstractSyntaxTree = Parser.Body
Expand Down Expand Up @@ -36,10 +38,10 @@ local function GetTypescriptType(State: State, Declaration: Type): (string, stri
local Values = ""

if Declaration.Type == "Primitive" then
local Tokens = (Declaration :: Parser.PrimitiveDeclaration).Tokens
local Tokens = (Declaration :: Parser.Primitive).Tokens
local Primitive = Primitives[Tokens.Primitive.Value]
if type(Primitive.Type) == "function" then
Type = Primitive.Type(Declaration :: Parser.PrimitiveDeclaration)
Type = Primitive.Type(Declaration :: Parser.Primitive)
else
Type = Primitive.Type
end
Expand All @@ -48,7 +50,7 @@ local function GetTypescriptType(State: State, Declaration: Type): (string, stri
Type = "unknown"
end
elseif Declaration.Type == "Set" then
local Value = (Declaration :: Parser.SetDeclaration).Value
local Value = (Declaration :: Parser.Set).Value
local Entries: {string} = {}

for _, Flag in Value.Values do
Expand All @@ -57,21 +59,21 @@ local function GetTypescriptType(State: State, Declaration: Type): (string, stri

Type = `\{{table.concat(Entries)}\}`
elseif Declaration.Type == "Enum" then
local Value = (Declaration :: Parser.EnumDeclaration).Value
local Value = (Declaration :: Parser.Enum).Value
Type = Util.GenerateEnumLiterals(Value.Values)
elseif Declaration.Type == "TagEnum" then
local Value = (Declaration :: Parser.TagEnumDeclaration).Value
local Value = (Declaration :: Parser.TagEnum).Value
local Literals = {}

for Index, Variant in Value.Values do
local TagField = `{Value.Tag}: "{Variant.Value.Identifier}"`
local TagField = `{Value.Tag}: "{Variant.Name}"`
local ValueType = GetTypescriptType(State, Variant)
table.insert(Literals, `\{ {TagField},{string.sub(ValueType, 2)}`)
end

Type = table.concat(Literals, " | ")
elseif Declaration.Type == "Map" then
local MapValue = (Declaration :: Parser.MapDeclaration).Value
local MapValue = (Declaration :: Parser.Map).Value
local Key = GetTypescriptType(State, MapValue.Values[1])
local Value = GetTypescriptType(State, MapValue.Values[2])
Type = `Map<{Key}, {Value}>`
Expand All @@ -80,21 +82,16 @@ local function GetTypescriptType(State: State, Declaration: Type): (string, stri
local Fields = {}

for _, Field in Value.Values do
local FieldValue = Field.Value
local Identifier = FieldValue.Identifier
local Name = Field.Name
local FieldType = GetTypescriptType(State, Field)
table.insert(Fields, `{Identifier}: {FieldType}`)
table.insert(Fields, `{Name}: {FieldType}`)
end

Type = `\{ {table.concat(Fields, ", ")}\ }`
elseif Declaration.Type == "Generic" then
Type = `{Declaration.Value.Generic}`
elseif Declaration.Type == "Reference" then
local Value = (Declaration :: Parser.ReferenceDeclaration).Value
local Reference = Value.Declaration.Value
Type = `{Util.GetScopePrefix(Reference.Scope, true, State.Scope)}{Reference.Identifier}`
elseif Declaration.Type == "Tuple" then
local Value = (Declaration :: Parser.TupleDeclaration).Value
local Value = (Declaration :: Parser.Tuple).Value
local TupleValues = Value.Values

local Types = {}
Expand All @@ -111,22 +108,15 @@ local function GetTypescriptType(State: State, Declaration: Type): (string, stri

Type = `{table.concat(Types, ", ")}`
Values = table.concat(VariableTypes, ", ")
elseif Declaration.Type == "Array" then
local Value = Declaration.Value
Type = `{GetTypescriptType(State, Value.Of)}[]`
elseif Declaration.Type == "Optional" then
local Value = Declaration.Value
Type = `{GetTypescriptType(State, Value.Of)} | undefined`
end

local Value = Declaration.Value
local Array = Value.Array

if Value.Optional then
Type = `{Type} | undefined`
end

if Array then
Type = `{Type}[]`
if Array.Optional then
Type = `{Type} | undefined`
end
end

if Value.Parameters then
local Parameters = {}

Expand All @@ -151,8 +141,8 @@ local function GetTypescriptType(State: State, Declaration: Type): (string, stri
end

function Generators.Type(State: State, Type: Type)
local Name = Type.Name
local Value = Type.Value
local Identifier = Value.Identifier

local Indent = State.Indent
local StringBuilder = State.Builder
Expand All @@ -162,34 +152,33 @@ function Generators.Type(State: State, Type: Type)
local Generics = ""
if Value.Generics then
local Types = {}
for Generic in Value.Generics.Indices do
for _, Generic in Value.Generics.List do
table.insert(Types, Generic)
end

Generics = `<{table.concat(Types, ",")}>`
end

StringBuilder.Push(`type {Identifier}{Generics} = {TypescriptType}`, 0, Indent)
StringBuilder.Push(`type {Name}{Generics} = {TypescriptType}`, 0, Indent)
end

function Generators.Export(State: State, Type: Type)
local Value = Type.Value
local Identifier = Value.Identifier
local Name = Type.Name

local Indent = State.Indent
local Casing = State.Casing
local StringBuilder = State.Builder

local Types, Values = GetTypescriptType(State, Type)
StringBuilder.Push(`{GetPrefix(Indent)}const {Identifier}: \{`, 0, Indent)
StringBuilder.Push(`{GetPrefix(Indent)}const {Name}: \{`, 0, Indent)
StringBuilder.Push(`{Casing.Read}: (Buffer: buffer) => {Types}`, 0, Indent + 1)
StringBuilder.Push(`{Casing.Write}: ({Values}) => buffer`, 0, Indent + 1)
StringBuilder.Push(`\}`, 0, Indent)
end

function Generators.Function(State: State, Function: Parser.FunctionDeclaration)
function Generators.Function(State: State, Function: Parser.Function)
local Name = Function.Name
local Value = Function.Value
local Identifier = Value.Identifier

local Indent = State.Indent
local Casing = State.Casing
Expand All @@ -205,7 +194,7 @@ function Generators.Function(State: State, Function: Parser.FunctionDeclaration)
ReturnTypes = GetTypescriptType(State, Value.Return)
end

StringBuilder.Push(`export {GetPrefix(Indent)}const {Identifier}: \{`, 0, Indent)
StringBuilder.Push(`export {GetPrefix(Indent)}const {Name}: \{`, 0, Indent)

if State.Context == "Server" then
StringBuilder.Push(`{Casing.On}: (Listener: (Player: Player, {Values}) => {ReturnTypes}) => void`, 0, Indent + 1)
Expand All @@ -220,9 +209,9 @@ function Generators.Function(State: State, Function: Parser.FunctionDeclaration)
StringBuilder.Push(`\}`, 0, Indent)
end

function Generators.Event(State: State, Event: Parser.EventDeclaration)
function Generators.Event(State: State, Event: Parser.Event)
local Name = Event.Name
local Value = Event.Value
local Identifier = Value.Identifier

local Indent = State.Indent
local Casing = State.Casing
Expand All @@ -245,7 +234,7 @@ function Generators.Event(State: State, Event: Parser.EventDeclaration)
ListenerValues = `LuaTuple<[{ListenerValues}]>`
end

StringBuilder.Push(`export {GetPrefix(Indent)}const {Identifier}: \{`, 0, Indent)
StringBuilder.Push(`export {GetPrefix(Indent)}const {Name}: \{`, 0, Indent)

if Value.From == State.Context then
if Value.From == "Server" then
Expand All @@ -265,9 +254,9 @@ function Generators.Event(State: State, Event: Parser.EventDeclaration)
StringBuilder.Push(`\}`, 0, Indent)
end

function Generators.Scope(State: State, Scope: Parser.ScopeDeclaration)
function Generators.Scope(State: State, Scope: Parser.ScopeNode)
local Name = Scope.Name
local Value = Scope.Value
local Identifier = Value.Identifier

local Parent = State.Scope
local Indent = State.Indent
Expand All @@ -276,7 +265,7 @@ function Generators.Scope(State: State, Scope: Parser.ScopeDeclaration)
State.Indent += 1
State.Scope = Value.Scope

StringBuilder.Push(`export {GetPrefix(Indent)}namespace {Identifier} \{`, 0, Indent)
StringBuilder.Push(`export {GetPrefix(Indent)}namespace {Name} \{`, 0, Indent)
Generators.Tree(State, Value.Values)
StringBuilder.Push(`}`, 0, Indent)

Expand All @@ -287,11 +276,11 @@ end
function Generators.Tree(State: State, Tree: {Parser.Declaration})
for Index, Declaration in Tree do
if Declaration.Type == "Scope" then
Generators.Scope(State, Declaration :: Parser.ScopeDeclaration)
Generators.Scope(State, Declaration :: Parser.ScopeNode)
elseif Declaration.Type == "Event" then
Generators.Event(State, Declaration :: Parser.EventDeclaration)
Generators.Event(State, Declaration :: Parser.Event)
elseif Declaration.Type == "Function" then
Generators.Function(State, Declaration :: Parser.FunctionDeclaration)
Generators.Function(State, Declaration :: Parser.Function)
else
if Declaration.Value.Export then
Generators.Export(State, Declaration :: Type)
Expand All @@ -304,7 +293,7 @@ end

return function(FileContext: Context, AbstractSyntaxTree: AbstractSyntaxTree): string
local Options = AbstractSyntaxTree.Value.Options
local Casing = Settings.GetCasing(Options.Casing or "Pascal")
local Casing = Settings.GetCasing(Options.Casing or "Pascal" :: any)
local StringBuilder = Builder.new()

StringBuilder.Push(VERSION_HEADER)
Expand Down
4 changes: 2 additions & 2 deletions src/Generator/Util.luau
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ type Scope = Parser.Scope
local function GetScopePrefix(ReferenceScope: Scope?, Dots: boolean?, CurrentScope: Scope): string
local Prefix = ""
local WorkingScope: Scope? = ReferenceScope or CurrentScope
while (WorkingScope and WorkingScope.Identifier.Value ~= "") do
Prefix = `{WorkingScope.Identifier.Value}{Dots and "." or "_"}` .. Prefix
while (WorkingScope and WorkingScope.Name.Value ~= "") do
Prefix = `{WorkingScope.Name.Value}{Dots and "." or "_"}` .. Prefix
WorkingScope = WorkingScope.Parent
end

Expand Down
Loading

0 comments on commit a641169

Please sign in to comment.