From 729ae78eaef65581585481972ced1d856f47d2e0 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sat, 3 Sep 2022 22:17:05 -0400 Subject: [PATCH 01/22] Location is now included in structs via composition --- parser/argument.go | 7 +++--- parser/data.go | 3 ++- parser/enum.go | 3 ++- parser/face.go | 2 +- parser/func.go | 3 ++- parser/node-traits.go | 30 +++++++++++++++++++++++ parser/objt.go | 3 ++- parser/tree.go | 56 +++++++++++++++++++++---------------------- parser/type.go | 3 ++- 9 files changed, 72 insertions(+), 38 deletions(-) create mode 100644 parser/node-traits.go diff --git a/parser/argument.go b/parser/argument.go index 5dd87e3..eae5085 100644 --- a/parser/argument.go +++ b/parser/argument.go @@ -16,7 +16,7 @@ var validArgumentStartTokens = []lexer.TokenKind { } func (parser *ParsingOperation) parseArgument () (argument Argument, err error) { - argument.location = parser.token.Location() + argument.setLocation(parser.token.Location()) err = parser.expect(validArgumentStartTokens...) if err != nil { return } @@ -44,9 +44,8 @@ func (parser *ParsingOperation) parseArgument () (argument Argument, err error) argument.kind = ArgumentKindDeclaration argument.value = Declaration { - location: argument.location, - name: identifier.trail[0], - what: what, + name: identifier.trail[0], + what: what, } } else { argument.kind = ArgumentKindIdentifier diff --git a/parser/data.go b/parser/data.go index eb828af..e4ab680 100644 --- a/parser/data.go +++ b/parser/data.go @@ -11,7 +11,8 @@ func (parser *ParsingOperation) parseDataSection () ( err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &DataSection { location: parser.token.Location() } + section = &DataSection { } + section.setLocation(parser.token.Location()) err = parser.nextToken(lexer.TokenKindPermission) if err != nil { return } diff --git a/parser/enum.go b/parser/enum.go index 23d318e..5c4463c 100644 --- a/parser/enum.go +++ b/parser/enum.go @@ -11,7 +11,8 @@ func (parser *ParsingOperation) parseEnumSection () ( err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &EnumSection { location: parser.token.Location() } + section = &EnumSection { } + section.setLocation(parser.token.Location()) // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/face.go b/parser/face.go index 14460cb..7cf715b 100644 --- a/parser/face.go +++ b/parser/face.go @@ -13,9 +13,9 @@ func (parser *ParsingOperation) parseFaceSection () ( if err != nil { return } section = &FaceSection { - location: parser.token.Location(), behaviors: make(map[string] FaceBehavior), } + section.setLocation(parser.token.Location()) // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/func.go b/parser/func.go index 1ee5302..5477a16 100644 --- a/parser/func.go +++ b/parser/func.go @@ -12,7 +12,8 @@ func (parser *ParsingOperation) parseFuncSection () ( err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &FuncSection { location: parser.token.Location() } + section = &FuncSection { } + section.setLocation(parser.token.Location()) // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/node-traits.go b/parser/node-traits.go new file mode 100644 index 0000000..dc81506 --- /dev/null +++ b/parser/node-traits.go @@ -0,0 +1,30 @@ +package parser + +import "git.tebibyte.media/arf/arf/file" +import "git.tebibyte.media/arf/arf/infoerr" + +// locatable allows a tree node to have a location. +type locatable struct { + location file.Location +} + +// Location returns the location of the node. +func (trait locatable) Location (location file.Location) { + location = trait.location + return +} + +// setLocation sets the location of the node. +func (trait locatable) setLocation (location file.Location) { + trait.location = location +} + +// NewError creates a new error at the node's location. +func (trait locatable) NewError ( + message string, + kind infoerr.ErrorKind, +) ( + err infoerr.Error, +) { + return infoerr.NewError(trait.location, message, kind) +} diff --git a/parser/objt.go b/parser/objt.go index 3c99acb..9603959 100644 --- a/parser/objt.go +++ b/parser/objt.go @@ -13,7 +13,8 @@ func (parser *ParsingOperation) parseObjtSection () ( err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &ObjtSection { location: parser.token.Location() } + section = &ObjtSection { } + section.setLocation(parser.token.Location()) // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/tree.go b/parser/tree.go index 257960a..64945b8 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -21,8 +21,8 @@ type SyntaxTree struct { // Identifier represents a chain of arguments separated by a dot. type Identifier struct { - location file.Location - trail []string + locatable + trail []string } // TypeKind represents what kind of type a type is @@ -42,7 +42,7 @@ const ( // Type represents a type specifier type Type struct { - location file.Location + locatable mutable bool kind TypeKind @@ -60,23 +60,23 @@ type Type struct { // Declaration represents a variable declaration. type Declaration struct { - location file.Location - name string - what Type + locatable + name string + what Type } // ObjectInitializationValues represents a list of object member initialization // attributes. type ObjectInitializationValues struct { - location file.Location + locatable attributes map[string] Argument } // ArrayInitializationValues represents a list of attributes initializing an // array. type ArrayInitializationValues struct { - location file.Location - values []Argument + locatable + values []Argument } // ArgumentKind specifies the type of thing the value of an argument should be @@ -139,17 +139,17 @@ const ( // Argument represents a value that can be placed anywhere a value goes. This // allows things like phrases being arguments to other phrases. type Argument struct { - location file.Location - kind ArgumentKind - value any + locatable + kind ArgumentKind + value any // TODO: if there is an argument expansion operator its existence should // be stored here in a boolean. } // DataSection represents a global variable. type DataSection struct { - location file.Location - name string + locatable + name string what Type permission types.Permission @@ -158,8 +158,8 @@ type DataSection struct { // TypeSection represents a blind type definition. type TypeSection struct { - location file.Location - name string + locatable + name string inherits Type permission types.Permission @@ -168,8 +168,8 @@ type TypeSection struct { // ObjtMember represents a part of an object type definition. type ObjtMember struct { - location file.Location - name string + locatable + name string what Type bitWidth uint64 @@ -179,8 +179,8 @@ type ObjtMember struct { // ObjtSection represents an object type definition. type ObjtSection struct { - location file.Location - name string + locatable + name string inherits Identifier permission types.Permission @@ -189,15 +189,15 @@ type ObjtSection struct { // EnumMember represents a member of an enum section. type EnumMember struct { - location file.Location - name string - value Argument + locatable + name string + value Argument } // EnumSection represents an enumerated type section. type EnumSection struct { - location file.Location - name string + locatable + name string what Type permission types.Permission @@ -206,7 +206,7 @@ type EnumSection struct { // FaceBehavior represents a behavior of an interface section. type FaceBehavior struct { - location file.Location + locatable name string inputs []Declaration @@ -215,7 +215,7 @@ type FaceBehavior struct { // FaceSection represents an interface type section. type FaceSection struct { - location file.Location + locatable name string inherits Identifier @@ -268,7 +268,7 @@ type FuncOutput struct { // FuncSection represents a function section. type FuncSection struct { - location file.Location + locatable name string permission types.Permission diff --git a/parser/type.go b/parser/type.go index 04bc9fd..cc4e60f 100644 --- a/parser/type.go +++ b/parser/type.go @@ -13,7 +13,8 @@ func (parser *ParsingOperation) parseTypeSection () ( err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &TypeSection { location: parser.token.Location() } + section = &TypeSection { } + section.setLocation(parser.token.Location()) // get permission err = parser.nextToken(lexer.TokenKindPermission) From 8e7421643012debd46f1d5a17c763440634d6471 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sat, 3 Sep 2022 22:33:34 -0400 Subject: [PATCH 02/22] Names are now composed from a nameable struct --- parser/argument.go | 12 ++++++++---- parser/node-traits.go | 19 +++++++++++++++++-- parser/tree.go | 20 ++++++++++---------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/parser/argument.go b/parser/argument.go index eae5085..c86b717 100644 --- a/parser/argument.go +++ b/parser/argument.go @@ -41,12 +41,16 @@ func (parser *ParsingOperation) parseArgument () (argument Argument, err error) infoerr.ErrorKindError) return } - - argument.kind = ArgumentKindDeclaration - argument.value = Declaration { - name: identifier.trail[0], + + declaration := Declaration { what: what, } + declaration.setName(identifier.trail[0]) + declaration.setLocation(argument.Location()) + + argument.kind = ArgumentKindDeclaration + argument.value = declaration + } else { argument.kind = ArgumentKindIdentifier argument.value = identifier diff --git a/parser/node-traits.go b/parser/node-traits.go index dc81506..d6ac5df 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -9,13 +9,13 @@ type locatable struct { } // Location returns the location of the node. -func (trait locatable) Location (location file.Location) { +func (trait locatable) Location () (location file.Location) { location = trait.location return } // setLocation sets the location of the node. -func (trait locatable) setLocation (location file.Location) { +func (trait* locatable) setLocation (location file.Location) { trait.location = location } @@ -28,3 +28,18 @@ func (trait locatable) NewError ( ) { return infoerr.NewError(trait.location, message, kind) } + +// nameable allows a tree node to have a name. +type nameable struct { + name string +} + +// Name returns the name of the node. +func (trait nameable) Name () (name string) { + name = trait.name + return +} +// setName sets the name of the node. +func (trait *nameable) setName (name string) { + trait.name = name +} diff --git a/parser/tree.go b/parser/tree.go index 64945b8..90cda2c 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -61,7 +61,7 @@ type Type struct { // Declaration represents a variable declaration. type Declaration struct { locatable - name string + nameable what Type } @@ -149,7 +149,7 @@ type Argument struct { // DataSection represents a global variable. type DataSection struct { locatable - name string + nameable what Type permission types.Permission @@ -159,7 +159,7 @@ type DataSection struct { // TypeSection represents a blind type definition. type TypeSection struct { locatable - name string + nameable inherits Type permission types.Permission @@ -169,7 +169,7 @@ type TypeSection struct { // ObjtMember represents a part of an object type definition. type ObjtMember struct { locatable - name string + nameable what Type bitWidth uint64 @@ -180,7 +180,7 @@ type ObjtMember struct { // ObjtSection represents an object type definition. type ObjtSection struct { locatable - name string + nameable inherits Identifier permission types.Permission @@ -190,14 +190,14 @@ type ObjtSection struct { // EnumMember represents a member of an enum section. type EnumMember struct { locatable - name string + nameable value Argument } // EnumSection represents an enumerated type section. type EnumSection struct { locatable - name string + nameable what Type permission types.Permission @@ -207,7 +207,7 @@ type EnumSection struct { // FaceBehavior represents a behavior of an interface section. type FaceBehavior struct { locatable - name string + nameable inputs []Declaration outputs []Declaration @@ -216,7 +216,7 @@ type FaceBehavior struct { // FaceSection represents an interface type section. type FaceSection struct { locatable - name string + nameable inherits Identifier permission types.Permission @@ -269,7 +269,7 @@ type FuncOutput struct { // FuncSection represents a function section. type FuncSection struct { locatable - name string + nameable permission types.Permission receiver *Declaration From ef375810fba14269db3320770ad6efb482dd1df1 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sat, 3 Sep 2022 22:56:08 -0400 Subject: [PATCH 03/22] Did the same thing with type specifiers --- parser/argument.go | 5 ++--- parser/node-traits.go | 15 +++++++++++++++ parser/tree-tostring.go | 2 +- parser/tree.go | 16 ++++++++-------- parser/type.go | 2 +- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/parser/argument.go b/parser/argument.go index c86b717..c56a8d7 100644 --- a/parser/argument.go +++ b/parser/argument.go @@ -42,9 +42,8 @@ func (parser *ParsingOperation) parseArgument () (argument Argument, err error) return } - declaration := Declaration { - what: what, - } + declaration := Declaration { } + declaration.what = what declaration.setName(identifier.trail[0]) declaration.setLocation(argument.Location()) diff --git a/parser/node-traits.go b/parser/node-traits.go index d6ac5df..3493aa6 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -43,3 +43,18 @@ func (trait nameable) Name () (name string) { func (trait *nameable) setName (name string) { trait.name = name } + +// typeable allows a node to have a type. +type typeable struct { + what Type +} + +// Type returns the type of the node. +func (trait typeable) Type () (what Type) { + return trait.what +} + +// setType sets the type of the node. +func (trait *typeable) setType (what Type) () { + +} diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 35a3d35..6ef1978 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -309,7 +309,7 @@ func (section *TypeSection) ToString (indent int) (output string) { "type ", section.permission.ToString(), " ", section.name, ":", - section.inherits.ToString()) + section.what.ToString()) isComplexInitialization := section.defaultValue.kind == ArgumentKindObjectInitializationValues || diff --git a/parser/tree.go b/parser/tree.go index 90cda2c..bf99c55 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -62,7 +62,7 @@ type Type struct { type Declaration struct { locatable nameable - what Type + typeable } // ObjectInitializationValues represents a list of object member initialization @@ -150,8 +150,8 @@ type Argument struct { type DataSection struct { locatable nameable + typeable - what Type permission types.Permission value Argument } @@ -160,8 +160,8 @@ type DataSection struct { type TypeSection struct { locatable nameable + typeable - inherits Type permission types.Permission defaultValue Argument } @@ -170,8 +170,8 @@ type TypeSection struct { type ObjtMember struct { locatable nameable - - what Type + typeable + bitWidth uint64 permission types.Permission defaultValue Argument @@ -181,8 +181,8 @@ type ObjtMember struct { type ObjtSection struct { locatable nameable + inherits Identifier - inherits Identifier permission types.Permission members []ObjtMember } @@ -198,8 +198,8 @@ type EnumMember struct { type EnumSection struct { locatable nameable - - what Type + typeable + permission types.Permission members []EnumMember } diff --git a/parser/type.go b/parser/type.go index cc4e60f..b6620c2 100644 --- a/parser/type.go +++ b/parser/type.go @@ -31,7 +31,7 @@ func (parser *ParsingOperation) parseTypeSection () ( if err != nil { return } err = parser.nextToken() if err != nil { return } - section.inherits, err = parser.parseType() + section.what, err = parser.parseType() if err != nil { return } // parse default values From 3f7c779e2b4b88db9671ca23e2fa4f0c67992016 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sat, 3 Sep 2022 22:58:35 -0400 Subject: [PATCH 04/22] Got rid of useless setters for the traits --- parser/argument.go | 6 +++--- parser/data.go | 2 +- parser/enum.go | 2 +- parser/face.go | 2 +- parser/func.go | 2 +- parser/node-traits.go | 15 --------------- parser/objt.go | 2 +- parser/type.go | 2 +- 8 files changed, 9 insertions(+), 24 deletions(-) diff --git a/parser/argument.go b/parser/argument.go index c56a8d7..e821322 100644 --- a/parser/argument.go +++ b/parser/argument.go @@ -16,7 +16,7 @@ var validArgumentStartTokens = []lexer.TokenKind { } func (parser *ParsingOperation) parseArgument () (argument Argument, err error) { - argument.setLocation(parser.token.Location()) + argument.location = parser.token.Location() err = parser.expect(validArgumentStartTokens...) if err != nil { return } @@ -44,8 +44,8 @@ func (parser *ParsingOperation) parseArgument () (argument Argument, err error) declaration := Declaration { } declaration.what = what - declaration.setName(identifier.trail[0]) - declaration.setLocation(argument.Location()) + declaration.name = identifier.trail[0] + declaration.location = argument.Location() argument.kind = ArgumentKindDeclaration argument.value = declaration diff --git a/parser/data.go b/parser/data.go index e4ab680..9597972 100644 --- a/parser/data.go +++ b/parser/data.go @@ -12,7 +12,7 @@ func (parser *ParsingOperation) parseDataSection () ( if err != nil { return } section = &DataSection { } - section.setLocation(parser.token.Location()) + section.location = parser.token.Location() err = parser.nextToken(lexer.TokenKindPermission) if err != nil { return } diff --git a/parser/enum.go b/parser/enum.go index 5c4463c..80577a7 100644 --- a/parser/enum.go +++ b/parser/enum.go @@ -12,7 +12,7 @@ func (parser *ParsingOperation) parseEnumSection () ( if err != nil { return } section = &EnumSection { } - section.setLocation(parser.token.Location()) + section.location = parser.token.Location() // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/face.go b/parser/face.go index 7cf715b..65e8372 100644 --- a/parser/face.go +++ b/parser/face.go @@ -15,7 +15,7 @@ func (parser *ParsingOperation) parseFaceSection () ( section = &FaceSection { behaviors: make(map[string] FaceBehavior), } - section.setLocation(parser.token.Location()) + section.location = parser.token.Location() // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/func.go b/parser/func.go index 5477a16..feb5d13 100644 --- a/parser/func.go +++ b/parser/func.go @@ -13,7 +13,7 @@ func (parser *ParsingOperation) parseFuncSection () ( if err != nil { return } section = &FuncSection { } - section.setLocation(parser.token.Location()) + section.location = parser.token.Location() // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/node-traits.go b/parser/node-traits.go index 3493aa6..d0e2df0 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -14,11 +14,6 @@ func (trait locatable) Location () (location file.Location) { return } -// setLocation sets the location of the node. -func (trait* locatable) setLocation (location file.Location) { - trait.location = location -} - // NewError creates a new error at the node's location. func (trait locatable) NewError ( message string, @@ -39,11 +34,6 @@ func (trait nameable) Name () (name string) { name = trait.name return } -// setName sets the name of the node. -func (trait *nameable) setName (name string) { - trait.name = name -} - // typeable allows a node to have a type. type typeable struct { what Type @@ -53,8 +43,3 @@ type typeable struct { func (trait typeable) Type () (what Type) { return trait.what } - -// setType sets the type of the node. -func (trait *typeable) setType (what Type) () { - -} diff --git a/parser/objt.go b/parser/objt.go index 9603959..8e40715 100644 --- a/parser/objt.go +++ b/parser/objt.go @@ -14,7 +14,7 @@ func (parser *ParsingOperation) parseObjtSection () ( if err != nil { return } section = &ObjtSection { } - section.setLocation(parser.token.Location()) + section.location = parser.token.Location() // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/type.go b/parser/type.go index b6620c2..cacc3b0 100644 --- a/parser/type.go +++ b/parser/type.go @@ -14,7 +14,7 @@ func (parser *ParsingOperation) parseTypeSection () ( if err != nil { return } section = &TypeSection { } - section.setLocation(parser.token.Location()) + section.location = parser.token.Location() // get permission err = parser.nextToken(lexer.TokenKindPermission) From e0a04e68e3ef7819f142574b227e7bf833f24dbd Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sat, 3 Sep 2022 23:03:09 -0400 Subject: [PATCH 05/22] Did the same thing but with permissions --- parser/enum.go | 1 + parser/node-traits.go | 17 +++++++++++++++-- parser/tree.go | 19 +++++++++---------- parser/type.go | 1 - 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/parser/enum.go b/parser/enum.go index 80577a7..228c9f0 100644 --- a/parser/enum.go +++ b/parser/enum.go @@ -4,6 +4,7 @@ import "git.tebibyte.media/arf/arf/types" import "git.tebibyte.media/arf/arf/lexer" import "git.tebibyte.media/arf/arf/infoerr" +// parseEnumSection parses an enumerated type section. func (parser *ParsingOperation) parseEnumSection () ( section *EnumSection, err error, diff --git a/parser/node-traits.go b/parser/node-traits.go index d0e2df0..29e64ce 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -1,6 +1,7 @@ package parser import "git.tebibyte.media/arf/arf/file" +import "git.tebibyte.media/arf/arf/types" import "git.tebibyte.media/arf/arf/infoerr" // locatable allows a tree node to have a location. @@ -21,7 +22,8 @@ func (trait locatable) NewError ( ) ( err infoerr.Error, ) { - return infoerr.NewError(trait.location, message, kind) + err = infoerr.NewError(trait.location, message, kind) + return } // nameable allows a tree node to have a name. @@ -41,5 +43,16 @@ type typeable struct { // Type returns the type of the node. func (trait typeable) Type () (what Type) { - return trait.what + what = trait.what + return +} + +// permissionable allows a node to have a permission. +type permissionable struct { + permission types.Permission +} + +func (trait permissionable) Permission () (permission types.Permission) { + permission = trait.permission + return } diff --git a/parser/tree.go b/parser/tree.go index bf99c55..d726cbf 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -1,7 +1,6 @@ package parser import "git.tebibyte.media/arf/arf/file" -import "git.tebibyte.media/arf/arf/types" // SyntaxTree represents an abstract syntax tree. It covers an entire module. It // can be expected to be syntactically correct, but it might not be semantically @@ -151,9 +150,9 @@ type DataSection struct { locatable nameable typeable + permissionable - permission types.Permission - value Argument + value Argument } // TypeSection represents a blind type definition. @@ -161,8 +160,8 @@ type TypeSection struct { locatable nameable typeable + permissionable - permission types.Permission defaultValue Argument } @@ -171,9 +170,9 @@ type ObjtMember struct { locatable nameable typeable + permissionable bitWidth uint64 - permission types.Permission defaultValue Argument } @@ -181,9 +180,9 @@ type ObjtMember struct { type ObjtSection struct { locatable nameable + permissionable inherits Identifier - permission types.Permission members []ObjtMember } @@ -199,9 +198,9 @@ type EnumSection struct { locatable nameable typeable + permissionable - permission types.Permission - members []EnumMember + members []EnumMember } // FaceBehavior represents a behavior of an interface section. @@ -217,9 +216,9 @@ type FaceBehavior struct { type FaceSection struct { locatable nameable + permissionable inherits Identifier - permission types.Permission behaviors map[string] FaceBehavior } @@ -270,7 +269,7 @@ type FuncOutput struct { type FuncSection struct { locatable nameable - permission types.Permission + permissionable receiver *Declaration inputs []Declaration diff --git a/parser/type.go b/parser/type.go index cacc3b0..5c484f2 100644 --- a/parser/type.go +++ b/parser/type.go @@ -2,7 +2,6 @@ package parser import "git.tebibyte.media/arf/arf/types" import "git.tebibyte.media/arf/arf/lexer" -// import "git.tebibyte.media/arf/arf/infoerr" // parseTypeSection parses a blind type definition, meaning it can inherit from // anything including primitives, but cannot define structure. From 899f4815bc1f6f6912b7a37b219ee3dadfba50fb Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 03:31:35 -0400 Subject: [PATCH 06/22] Did the same thing with default values --- parser/func.go | 4 ++-- parser/node-traits.go | 12 ++++++++++++ parser/objt.go | 4 ++-- parser/tree-tostring.go | 24 ++++++++++++------------ parser/tree.go | 9 ++++----- parser/type.go | 4 ++-- 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/parser/func.go b/parser/func.go index feb5d13..b42fe0e 100644 --- a/parser/func.go +++ b/parser/func.go @@ -186,12 +186,12 @@ func (parser *ParsingOperation) parseFuncArguments ( err = parser.nextToken() if err != nil { return } - output.defaultValue, err = + output.value, err = parser.parseInitializationValues(1) into.outputs = append(into.outputs, output) if err != nil { return } } else { - output.defaultValue, err = + output.value, err = parser.parseArgument() into.outputs = append(into.outputs, output) if err != nil { return } diff --git a/parser/node-traits.go b/parser/node-traits.go index 29e64ce..4a3f66e 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -52,7 +52,19 @@ type permissionable struct { permission types.Permission } +// Permission returns the permision of the node. func (trait permissionable) Permission () (permission types.Permission) { permission = trait.permission return } + +// valuable allows a node to have an argument value. +type valuable struct { + value Argument +} + +// Value returns the value argument of the node. +func (trait valuable) Value () (value Argument) { + value = trait.value + return +} diff --git a/parser/objt.go b/parser/objt.go index 8e40715..ca72df4 100644 --- a/parser/objt.go +++ b/parser/objt.go @@ -109,11 +109,11 @@ func (parser *ParsingOperation) parseObjtMember () ( err = parser.nextToken() if err != nil { return } - member.defaultValue, + member.value, err = parser.parseInitializationValues(1) if err != nil { return } } else { - member.defaultValue, err = parser.parseArgument() + member.value, err = parser.parseArgument() if err != nil { return } err = parser.expect(lexer.TokenKindNewline) diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index 6ef1978..ebd080d 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -312,16 +312,16 @@ func (section *TypeSection) ToString (indent int) (output string) { section.what.ToString()) isComplexInitialization := - section.defaultValue.kind == ArgumentKindObjectInitializationValues || - section.defaultValue.kind == ArgumentKindArrayInitializationValues + section.value.kind == ArgumentKindObjectInitializationValues || + section.value.kind == ArgumentKindArrayInitializationValues - if section.defaultValue.value == nil { + if section.value.value == nil { output += "\n" } else if isComplexInitialization { output += "\n" - output += section.defaultValue.ToString(indent + 1, true) + output += section.value.ToString(indent + 1, true) } else { - output += " " + section.defaultValue.ToString(0, false) + output += " " + section.value.ToString(0, false) output += "\n" } return @@ -339,16 +339,16 @@ func (member ObjtMember) ToString (indent int) (output string) { } isComplexInitialization := - member.defaultValue.kind == ArgumentKindObjectInitializationValues || - member.defaultValue.kind == ArgumentKindArrayInitializationValues + member.value.kind == ArgumentKindObjectInitializationValues || + member.value.kind == ArgumentKindArrayInitializationValues - if member.defaultValue.value == nil { + if member.value.value == nil { output += "\n" } else if isComplexInitialization { output += "\n" - output += member.defaultValue.ToString(indent + 1, true) + output += member.value.ToString(indent + 1, true) } else { - output += " " + member.defaultValue.ToString(0, false) + output += " " + member.value.ToString(0, false) output += "\n" } @@ -473,8 +473,8 @@ func (block Block) ToString (indent int) (output string) { func (funcOutput FuncOutput) ToString () (output string) { output += funcOutput.Declaration.ToString() - if funcOutput.defaultValue.kind != ArgumentKindNil { - output += " " + funcOutput.defaultValue.ToString(0, false) + if funcOutput.value.kind != ArgumentKindNil { + output += " " + funcOutput.value.ToString(0, false) } return } diff --git a/parser/tree.go b/parser/tree.go index d726cbf..98cf23e 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -161,8 +161,7 @@ type TypeSection struct { nameable typeable permissionable - - defaultValue Argument + valuable } // ObjtMember represents a part of an object type definition. @@ -171,9 +170,9 @@ type ObjtMember struct { nameable typeable permissionable + valuable bitWidth uint64 - defaultValue Argument } // ObjtSection represents an object type definition. @@ -190,7 +189,7 @@ type ObjtSection struct { type EnumMember struct { locatable nameable - value Argument + valuable } // EnumSection represents an enumerated type section. @@ -262,7 +261,7 @@ type Block []Phrase // that it can have a default value. type FuncOutput struct { Declaration - defaultValue Argument + valuable } // FuncSection represents a function section. diff --git a/parser/type.go b/parser/type.go index 5c484f2..a00c8e7 100644 --- a/parser/type.go +++ b/parser/type.go @@ -38,10 +38,10 @@ func (parser *ParsingOperation) parseTypeSection () ( err = parser.nextToken() if err != nil { return } - section.defaultValue, err = parser.parseInitializationValues(0) + section.value, err = parser.parseInitializationValues(0) if err != nil { return } } else { - section.defaultValue, err = parser.parseArgument() + section.value, err = parser.parseArgument() if err != nil { return } err = parser.expect(lexer.TokenKindNewline) From ded0ce58ecd5e8b6f6520912cded87d5c5d47b5e Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 14:02:48 -0400 Subject: [PATCH 07/22] Created Section interface --- parser/accessors.go | 37 +++++++++++++++++++++++++++++++++++++ parser/body.go | 2 ++ parser/tree.go | 18 ++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 parser/accessors.go diff --git a/parser/accessors.go b/parser/accessors.go new file mode 100644 index 0000000..37633cb --- /dev/null +++ b/parser/accessors.go @@ -0,0 +1,37 @@ +package parser + +// Kind returns the section's kind (SectionKindType). +func (section TypeSection) Kind () (kind SectionKind) { + kind = SectionKindType + return +} + +// Kind returns the section's kind (SectionKindObjt). +func (section ObjtSection) Kind () (kind SectionKind) { + kind = SectionKindObjt + return +} + +// Kind returns the section's kind (SectionKindEnum). +func (section EnumSection) Kind () (kind SectionKind) { + kind = SectionKindEnum + return +} + +// Kind returns the section's kind (SectionKindFace). +func (section FaceSection) Kind () (kind SectionKind) { + kind = SectionKindFace + return +} + +// Kind returns the section's kind (SectionKindData). +func (section DataSection) Kind () (kind SectionKind) { + kind = SectionKindData + return +} + +// Kind returns the section's kind (SectionKindFunc). +func (section FuncSection) Kind () (kind SectionKind) { + kind = SectionKindFunc + return +} diff --git a/parser/body.go b/parser/body.go index 82001fc..8ca2722 100644 --- a/parser/body.go +++ b/parser/body.go @@ -3,6 +3,8 @@ package parser import "git.tebibyte.media/arf/arf/lexer" import "git.tebibyte.media/arf/arf/infoerr" +// TODO: parser must ensure that these names are unique + // parse body parses the body of an arf file, after the metadata header. func (parser *ParsingOperation) parseBody () (err error) { for { diff --git a/parser/tree.go b/parser/tree.go index 98cf23e..e505028 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -18,6 +18,24 @@ type SyntaxTree struct { funcSections map[string] *FuncSection } +// SectionKind differentiates Section interfaces. +type SectionKind int + +const ( + SectionKindType = iota + SectionKindObjt + SectionKindEnum + SectionKindFace + SectionKindData + SectionKindFunc +) + +// Section can be any kind of section. You can find out what type of section it +// is with the Kind method. +type Section interface { + Kind () (kind SectionKind) +} + // Identifier represents a chain of arguments separated by a dot. type Identifier struct { locatable From d930e72c0c3644bb6d9575fbf1da6137efe51296 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 14:04:48 -0400 Subject: [PATCH 08/22] Added more methods to the section interface --- parser/tree.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/parser/tree.go b/parser/tree.go index e505028..707f201 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -1,6 +1,7 @@ package parser import "git.tebibyte.media/arf/arf/file" +import "git.tebibyte.media/arf/arf/types" // SyntaxTree represents an abstract syntax tree. It covers an entire module. It // can be expected to be syntactically correct, but it might not be semantically @@ -33,7 +34,10 @@ const ( // Section can be any kind of section. You can find out what type of section it // is with the Kind method. type Section interface { - Kind () (kind SectionKind) + Location () (location file.Location) + Kind () (kind SectionKind) + Permission () (permission types.Permission) + Name () (name string) } // Identifier represents a chain of arguments separated by a dot. From 9269161138c658272237f982e4f720682050a955 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 17:13:49 -0400 Subject: [PATCH 09/22] Tree returns a section interface when given a name --- parser/accessors.go | 7 +++++++ parser/body.go | 14 +++++++++++++- parser/tree.go | 4 +++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/parser/accessors.go b/parser/accessors.go index 37633cb..92c72f6 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -1,5 +1,12 @@ package parser +// LookupSection looks returns the section under the give name. If the section +// does not exist, nil is returned. +func (tree *SyntaxTree) LookupSection (name string) (section Section) { + section = tree.sections[name] + return +} + // Kind returns the section's kind (SectionKindType). func (section TypeSection) Kind () (kind SectionKind) { kind = SectionKindType diff --git a/parser/body.go b/parser/body.go index 8ca2722..f7f338a 100644 --- a/parser/body.go +++ b/parser/body.go @@ -10,8 +10,8 @@ func (parser *ParsingOperation) parseBody () (err error) { for { err = parser.expect(lexer.TokenKindName) if err != nil { return } - sectionType := parser.token.Value().(string) + switch sectionType { case "data": var section *DataSection @@ -21,7 +21,9 @@ func (parser *ParsingOperation) parseBody () (err error) { make(map[string] *DataSection) } parser.tree.dataSections[section.name] = section + parser.tree.sections[section.name] = section if err != nil { return } + case "type": var section *TypeSection section, err = parser.parseTypeSection() @@ -30,7 +32,9 @@ func (parser *ParsingOperation) parseBody () (err error) { make(map[string] *TypeSection) } parser.tree.typeSections[section.name] = section + parser.tree.sections[section.name] = section if err != nil { return } + case "objt": var section *ObjtSection section, err = parser.parseObjtSection() @@ -39,7 +43,9 @@ func (parser *ParsingOperation) parseBody () (err error) { make(map[string] *ObjtSection) } parser.tree.objtSections[section.name] = section + parser.tree.sections[section.name] = section if err != nil { return } + case "face": var section *FaceSection section, err = parser.parseFaceSection() @@ -48,7 +54,9 @@ func (parser *ParsingOperation) parseBody () (err error) { make(map[string] *FaceSection) } parser.tree.faceSections[section.name] = section + parser.tree.sections[section.name] = section if err != nil { return } + case "enum": var section *EnumSection section, err = parser.parseEnumSection() @@ -57,7 +65,9 @@ func (parser *ParsingOperation) parseBody () (err error) { make(map[string] *EnumSection) } parser.tree.enumSections[section.name] = section + parser.tree.sections[section.name] = section if err != nil { return } + case "func": var section *FuncSection section, err = parser.parseFuncSection() @@ -66,7 +76,9 @@ func (parser *ParsingOperation) parseBody () (err error) { make(map[string] *FuncSection) } parser.tree.funcSections[section.name] = section + parser.tree.sections[section.name] = section if err != nil { return } + default: err = parser.token.NewError ( "unknown section type \"" + sectionType + "\"", diff --git a/parser/tree.go b/parser/tree.go index 707f201..250bd8c 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -10,7 +10,9 @@ type SyntaxTree struct { license string author string - requires []string + requires []string + sections map[string] Section + typeSections map[string] *TypeSection objtSections map[string] *ObjtSection enumSections map[string] *EnumSection From f3c72f8f30ed2c3f2c0bd2b21ac34dbc2a6c1f61 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 19:30:59 -0400 Subject: [PATCH 10/22] The section kind specific maps are gone I've REPLACED IT with the unified sections map. Interfaces, baby! --- parser/body.go | 95 +++++++++++++++++------------------------ parser/node-traits.go | 2 +- parser/parser.go | 10 +++-- parser/tree-tostring.go | 30 ++----------- parser/tree.go | 10 ++--- 5 files changed, 53 insertions(+), 94 deletions(-) diff --git a/parser/body.go b/parser/body.go index f7f338a..cf48d55 100644 --- a/parser/body.go +++ b/parser/body.go @@ -11,73 +11,43 @@ func (parser *ParsingOperation) parseBody () (err error) { err = parser.expect(lexer.TokenKindName) if err != nil { return } sectionType := parser.token.Value().(string) - + switch sectionType { case "data": - var section *DataSection - section, err = parser.parseDataSection() - if parser.tree.dataSections == nil { - parser.tree.dataSections = - make(map[string] *DataSection) - } - parser.tree.dataSections[section.name] = section - parser.tree.sections[section.name] = section - if err != nil { return } + section, parseErr := parser.parseDataSection() + err = parser.tree.addSection(section) + if err != nil { return } + if parseErr != nil { return } case "type": - var section *TypeSection - section, err = parser.parseTypeSection() - if parser.tree.typeSections == nil { - parser.tree.typeSections = - make(map[string] *TypeSection) - } - parser.tree.typeSections[section.name] = section - parser.tree.sections[section.name] = section - if err != nil { return } + section, parseErr := parser.parseTypeSection() + err = parser.tree.addSection(section) + if err != nil { return } + if parseErr != nil { return } case "objt": - var section *ObjtSection - section, err = parser.parseObjtSection() - if parser.tree.objtSections == nil { - parser.tree.objtSections = - make(map[string] *ObjtSection) - } - parser.tree.objtSections[section.name] = section - parser.tree.sections[section.name] = section - if err != nil { return } + section, parseErr := parser.parseObjtSection() + err = parser.tree.addSection(section) + if err != nil { return } + if parseErr != nil { return } case "face": - var section *FaceSection - section, err = parser.parseFaceSection() - if parser.tree.faceSections == nil { - parser.tree.faceSections = - make(map[string] *FaceSection) - } - parser.tree.faceSections[section.name] = section - parser.tree.sections[section.name] = section - if err != nil { return } + section, parseErr := parser.parseFaceSection() + err = parser.tree.addSection(section) + if err != nil { return } + if parseErr != nil { return } case "enum": - var section *EnumSection - section, err = parser.parseEnumSection() - if parser.tree.enumSections == nil { - parser.tree.enumSections = - make(map[string] *EnumSection) - } - parser.tree.enumSections[section.name] = section - parser.tree.sections[section.name] = section - if err != nil { return } + section, parseErr := parser.parseEnumSection() + err = parser.tree.addSection(section) + if err != nil { return } + if parseErr != nil { return } case "func": - var section *FuncSection - section, err = parser.parseFuncSection() - if parser.tree.funcSections == nil { - parser.tree.funcSections = - make(map[string] *FuncSection) - } - parser.tree.funcSections[section.name] = section - parser.tree.sections[section.name] = section - if err != nil { return } + section, parseErr := parser.parseFuncSection() + err = parser.tree.addSection(section) + if err != nil { return } + if parseErr != nil { return } default: err = parser.token.NewError ( @@ -87,3 +57,18 @@ func (parser *ParsingOperation) parseBody () (err error) { } } } + +// addSection adds a section to the tree, ensuring it has a unique name within +// the module. +func (tree *SyntaxTree) addSection (section Section) (err error) { + _, exists := tree.sections[section.Name()] + if exists { + err = section.NewError ( + "cannot have multiple sections with the same name", + infoerr.ErrorKindError) + return + } + + tree.sections[section.Name()] = section + return +} diff --git a/parser/node-traits.go b/parser/node-traits.go index 4a3f66e..e16aeaf 100644 --- a/parser/node-traits.go +++ b/parser/node-traits.go @@ -20,7 +20,7 @@ func (trait locatable) NewError ( message string, kind infoerr.ErrorKind, ) ( - err infoerr.Error, + err error, ) { err = infoerr.NewError(trait.location, message, kind) return diff --git a/parser/parser.go b/parser/parser.go index 226665f..3a07318 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -20,7 +20,12 @@ type ParsingOperation struct { // Parse reads the files located in the module specified by modulePath, and // converts them into an abstract syntax tree. func Parse (modulePath string) (tree *SyntaxTree, err error) { - parser := ParsingOperation { modulePath: modulePath } + parser := ParsingOperation { + modulePath: modulePath, + tree: &SyntaxTree { + sections: make(map[string] Section), + }, + } if parser.modulePath[len(parser.modulePath) - 1] != '/' { parser.modulePath += "/" @@ -54,9 +59,6 @@ func (parser *ParsingOperation) parse (sourceFile *file.File) (err error) { if err != nil { return } // reset the parser - if parser.tree == nil { - parser.tree = &SyntaxTree { } - } if len(tokens) == 0 { return } parser.tokens = tokens parser.token = tokens[0] diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index ebd080d..c0dfc2e 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -47,35 +47,11 @@ func (tree *SyntaxTree) ToString (indent int) (output string) { output += doIndent(indent, "---\n") - typeSectionKeys := sortMapKeysAlphabetically(tree.typeSections) - for _, name := range typeSectionKeys { - output += tree.typeSections[name].ToString(indent) + sectionKeys := sortMapKeysAlphabetically(tree.sections) + for _, name := range sectionKeys { + output += tree.sections[name].ToString(indent) } - objtSectionKeys := sortMapKeysAlphabetically(tree.objtSections) - for _, name := range objtSectionKeys { - output += tree.objtSections[name].ToString(indent) - } - - enumSectionKeys := sortMapKeysAlphabetically(tree.enumSections) - for _, name := range enumSectionKeys { - output += tree.enumSections[name].ToString(indent) - } - - faceSectionKeys := sortMapKeysAlphabetically(tree.faceSections) - for _, name := range faceSectionKeys { - output += tree.faceSections[name].ToString(indent) - } - - dataSectionKeys := sortMapKeysAlphabetically(tree.dataSections) - for _, name := range dataSectionKeys { - output += tree.dataSections[name].ToString(indent) - } - - funcSectionKeys := sortMapKeysAlphabetically(tree.funcSections) - for _, name := range funcSectionKeys { - output += tree.funcSections[name].ToString(indent) - } return } diff --git a/parser/tree.go b/parser/tree.go index 250bd8c..0a2b953 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -2,6 +2,7 @@ package parser import "git.tebibyte.media/arf/arf/file" import "git.tebibyte.media/arf/arf/types" +import "git.tebibyte.media/arf/arf/infoerr" // SyntaxTree represents an abstract syntax tree. It covers an entire module. It // can be expected to be syntactically correct, but it might not be semantically @@ -12,13 +13,6 @@ type SyntaxTree struct { requires []string sections map[string] Section - - typeSections map[string] *TypeSection - objtSections map[string] *ObjtSection - enumSections map[string] *EnumSection - faceSections map[string] *FaceSection - dataSections map[string] *DataSection - funcSections map[string] *FuncSection } // SectionKind differentiates Section interfaces. @@ -40,6 +34,8 @@ type Section interface { Kind () (kind SectionKind) Permission () (permission types.Permission) Name () (name string) + NewError (message string, kind infoerr.ErrorKind) (err error) + ToString (indent int) (output string) } // Identifier represents a chain of arguments separated by a dot. From 691df94ef4c48743701b8796c5e843d8faa893b2 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 19:55:47 -0400 Subject: [PATCH 11/22] Removed many cringe pass-by-references --- parser/body.go | 2 -- parser/data.go | 3 +-- parser/enum.go | 5 ++--- parser/face.go | 8 +++----- parser/func.go | 5 ++--- parser/objt.go | 5 ++--- parser/tree-tostring.go | 20 ++++++++++---------- parser/tree.go | 5 ++--- parser/type.go | 3 +-- 9 files changed, 23 insertions(+), 33 deletions(-) diff --git a/parser/body.go b/parser/body.go index cf48d55..15b9092 100644 --- a/parser/body.go +++ b/parser/body.go @@ -3,8 +3,6 @@ package parser import "git.tebibyte.media/arf/arf/lexer" import "git.tebibyte.media/arf/arf/infoerr" -// TODO: parser must ensure that these names are unique - // parse body parses the body of an arf file, after the metadata header. func (parser *ParsingOperation) parseBody () (err error) { for { diff --git a/parser/data.go b/parser/data.go index 9597972..fa19ff0 100644 --- a/parser/data.go +++ b/parser/data.go @@ -5,13 +5,12 @@ import "git.tebibyte.media/arf/arf/lexer" // parseData parses a data section. func (parser *ParsingOperation) parseDataSection () ( - section *DataSection, + section DataSection, err error, ) { err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &DataSection { } section.location = parser.token.Location() err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/enum.go b/parser/enum.go index 228c9f0..9625dc5 100644 --- a/parser/enum.go +++ b/parser/enum.go @@ -6,13 +6,12 @@ import "git.tebibyte.media/arf/arf/infoerr" // parseEnumSection parses an enumerated type section. func (parser *ParsingOperation) parseEnumSection () ( - section *EnumSection, + section EnumSection, err error, ) { err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &EnumSection { } section.location = parser.token.Location() // get permission @@ -38,7 +37,7 @@ func (parser *ParsingOperation) parseEnumSection () ( if err != nil { return } // parse members - err = parser.parseEnumMembers(section) + err = parser.parseEnumMembers(§ion) if err != nil { return } if len(section.members) == 0 { diff --git a/parser/face.go b/parser/face.go index 65e8372..62f2605 100644 --- a/parser/face.go +++ b/parser/face.go @@ -6,16 +6,14 @@ import "git.tebibyte.media/arf/arf/infoerr" // parseFaceSection parses an interface section. func (parser *ParsingOperation) parseFaceSection () ( - section *FaceSection, + section FaceSection, err error, ) { err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &FaceSection { - behaviors: make(map[string] FaceBehavior), - } - section.location = parser.token.Location() + section.behaviors = make(map[string] FaceBehavior) + section.location = parser.token.Location() // get permission err = parser.nextToken(lexer.TokenKindPermission) diff --git a/parser/func.go b/parser/func.go index b42fe0e..f6288f5 100644 --- a/parser/func.go +++ b/parser/func.go @@ -6,13 +6,12 @@ import "git.tebibyte.media/arf/arf/infoerr" // parseFunc parses a function section. func (parser *ParsingOperation) parseFuncSection () ( - section *FuncSection, + section FuncSection, err error, ) { err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &FuncSection { } section.location = parser.token.Location() // get permission @@ -30,7 +29,7 @@ func (parser *ParsingOperation) parseFuncSection () ( if err != nil { return } err = parser.nextToken() if err != nil { return } - err = parser.parseFuncArguments(section) + err = parser.parseFuncArguments(§ion) if err != nil { return } // check to see if the function is external diff --git a/parser/objt.go b/parser/objt.go index ca72df4..1e83e98 100644 --- a/parser/objt.go +++ b/parser/objt.go @@ -7,13 +7,12 @@ import "git.tebibyte.media/arf/arf/infoerr" // parseObjtSection parses an object type definition. This allows for structured // types to be defined, and for member variables to be added and overridden. func (parser *ParsingOperation) parseObjtSection () ( - section *ObjtSection, + section ObjtSection, err error, ) { err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &ObjtSection { } section.location = parser.token.Location() // get permission @@ -39,7 +38,7 @@ func (parser *ParsingOperation) parseObjtSection () ( if err != nil { return } // parse members - err = parser.parseObjtMembers(section) + err = parser.parseObjtMembers(§ion) if err != nil { return } if len(section.members) == 0 { diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index c0dfc2e..ddc5ef2 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -30,7 +30,7 @@ func sortMapKeysAlphabetically[KEY_TYPE any] ( return } -func (tree *SyntaxTree) ToString (indent int) (output string) { +func (tree SyntaxTree) ToString (indent int) (output string) { output += doIndent(indent, ":arf\n") if tree.author != "" { @@ -66,7 +66,7 @@ func (identifier Identifier) ToString () (output string) { return } -func (what *Type) ToString () (output string) { +func (what Type) ToString () (output string) { if what.kind == TypeKindBasic { output += what.name.ToString() } else { @@ -130,7 +130,7 @@ func (values ArrayInitializationValues) ToString ( return } -func (argument *Argument) ToString (indent int, breakLine bool) (output string) { +func (argument Argument) ToString (indent int, breakLine bool) (output string) { if !breakLine { indent = 0 } if argument.kind == ArgumentKindNil { output += "NIL-ARGUMENT" @@ -255,7 +255,7 @@ func (argument *Argument) ToString (indent int, breakLine bool) (output string) return } -func (section *DataSection) ToString (indent int) (output string) { +func (section DataSection) ToString (indent int) (output string) { output += doIndent ( indent, "data ", @@ -279,7 +279,7 @@ func (section *DataSection) ToString (indent int) (output string) { return } -func (section *TypeSection) ToString (indent int) (output string) { +func (section TypeSection) ToString (indent int) (output string) { output += doIndent ( indent, "type ", @@ -331,7 +331,7 @@ func (member ObjtMember) ToString (indent int) (output string) { return } -func (section *ObjtSection) ToString (indent int) (output string) { +func (section ObjtSection) ToString (indent int) (output string) { output += doIndent ( indent, "objt ", @@ -345,7 +345,7 @@ func (section *ObjtSection) ToString (indent int) (output string) { return } -func (section *EnumSection) ToString (indent int) (output string) { +func (section EnumSection) ToString (indent int) (output string) { output += doIndent ( indent, "enum ", @@ -373,7 +373,7 @@ func (section *EnumSection) ToString (indent int) (output string) { return } -func (section *FaceSection) ToString (indent int) (output string) { +func (section FaceSection) ToString (indent int) (output string) { output += doIndent ( indent, "face ", @@ -388,7 +388,7 @@ func (section *FaceSection) ToString (indent int) (output string) { return } -func (behavior *FaceBehavior) ToString (indent int) (output string) { +func (behavior FaceBehavior) ToString (indent int) (output string) { output += doIndent(indent, behavior.name, "\n") for _, inputItem := range behavior.inputs { @@ -455,7 +455,7 @@ func (funcOutput FuncOutput) ToString () (output string) { return } -func (section *FuncSection) ToString (indent int) (output string) { +func (section FuncSection) ToString (indent int) (output string) { output += doIndent ( indent, "func ", diff --git a/parser/tree.go b/parser/tree.go index 0a2b953..e51e280 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -171,8 +171,7 @@ type DataSection struct { nameable typeable permissionable - - value Argument + valuable } // TypeSection represents a blind type definition. @@ -202,7 +201,7 @@ type ObjtSection struct { permissionable inherits Identifier - members []ObjtMember + members []ObjtMember } // EnumMember represents a member of an enum section. diff --git a/parser/type.go b/parser/type.go index a00c8e7..309e543 100644 --- a/parser/type.go +++ b/parser/type.go @@ -6,13 +6,12 @@ import "git.tebibyte.media/arf/arf/lexer" // parseTypeSection parses a blind type definition, meaning it can inherit from // anything including primitives, but cannot define structure. func (parser *ParsingOperation) parseTypeSection () ( - section *TypeSection, + section TypeSection, err error, ) { err = parser.expect(lexer.TokenKindName) if err != nil { return } - section = &TypeSection { } section.location = parser.token.Location() // get permission From 57b98636d05ccb5b3e4c3020dc5ff24a53c79c30 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 22:19:19 -0400 Subject: [PATCH 12/22] Added accessors for Identifier and Type --- parser/accessors.go | 51 +++++++++++++++++++++++++++++++++++++++++++++ parser/tree.go | 3 +++ 2 files changed, 54 insertions(+) diff --git a/parser/accessors.go b/parser/accessors.go index 92c72f6..0781bec 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -42,3 +42,54 @@ func (section FuncSection) Kind () (kind SectionKind) { kind = SectionKindFunc return } + +// Length returns the amount of names in the identifier. +func (identifier Identifier) Length () (length int) { + length = len(identifier.trail) + return +} + +// Item returns the name at the specified index. +func (identifier Identifier) Item (index int) (item string) { + item = identifier.trail[index] + return +} + +// Kind returns the type's kind. +func (what Type) Kind () (kind TypeKind) { + kind = what.kind + return +} + +// Mutable returns whether or not the type's data is mutable. +func (what Type) Mutable () (mutable bool) { + mutable = what.mutable + return +} + +// Length returns the length of the type if the type is an array. If the result +// is 0, this means the array has an undefined/variable length. +func (what Type) Length () (length uint64) { + if what.kind == TypeKindArray { + length = what.length + } + return +} + +// Name returns the name of the type, if it is a basic type. Otherwise, it +// returns a zero value identifier. +func (what Type) Name () (name Identifier) { + if what.kind == TypeKindBasic { + name = what.name + } + return +} + +// Points returns the type that this type points to, or is an array of. If the +// type is a basic type, this returns a zero value type. +func (what Type) Points () (points Type) { + if what.kind != TypeKindBasic { + points = *what.points + } + return +} diff --git a/parser/tree.go b/parser/tree.go index e51e280..2d1eade 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -57,6 +57,9 @@ const ( // TypeKindArray means it's an array. TypeKindArray + + // TODO: add a type kind for arrays with a variable amount of elements, + // because they are very much different concepts ) // Type represents a type specifier From 7af575e865bd08df0ef11337479494e7cfda249c Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 22:27:06 -0400 Subject: [PATCH 13/22] Added TypeKindVariableArray --- parser/accessors.go | 4 ++-- parser/misc.go | 2 +- parser/tree-tostring.go | 9 +++------ parser/tree.go | 11 +++++------ 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/parser/accessors.go b/parser/accessors.go index 0781bec..3a207ce 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -67,8 +67,8 @@ func (what Type) Mutable () (mutable bool) { return } -// Length returns the length of the type if the type is an array. If the result -// is 0, this means the array has an undefined/variable length. +// Length returns the length of the type if the type is a fixed length array. +// Otherwise, it just returns zero. func (what Type) Length () (length uint64) { if what.kind == TypeKindArray { length = what.length diff --git a/parser/misc.go b/parser/misc.go index 0901cdc..121df15 100644 --- a/parser/misc.go +++ b/parser/misc.go @@ -34,7 +34,7 @@ func (parser *ParsingOperation) parseType () (what Type, err error) { err = parser.nextToken(lexer.TokenKindRBrace) if err != nil { return } } else if parser.token.Is(lexer.TokenKindElipsis) { - what.kind = TypeKindArray + what.kind = TypeKindVariableArray err = parser.nextToken(lexer.TokenKindRBrace) if err != nil { return } diff --git a/parser/tree-tostring.go b/parser/tree-tostring.go index ddc5ef2..78dd94c 100644 --- a/parser/tree-tostring.go +++ b/parser/tree-tostring.go @@ -74,12 +74,9 @@ func (what Type) ToString () (output string) { output += what.points.ToString() if what.kind == TypeKindArray { - output += " " - if what.length == 0 { - output += ".." - } else { - output += fmt.Sprint(what.length) - } + output += fmt.Sprint(" ", what.length) + } else if what.kind == TypeKindVariableArray { + output += " .." } output += "}" diff --git a/parser/tree.go b/parser/tree.go index 2d1eade..d563942 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -38,7 +38,7 @@ type Section interface { ToString (indent int) (output string) } -// Identifier represents a chain of arguments separated by a dot. +// Identifier represents a chain of names separated by a dot. type Identifier struct { locatable trail []string @@ -55,11 +55,11 @@ const ( // TypeKindPointer means it's a pointer TypeKindPointer - // TypeKindArray means it's an array. + // TypeKindArray means it's a fixed length array. TypeKindArray - // TODO: add a type kind for arrays with a variable amount of elements, - // because they are very much different concepts + // TypeKindVariableArray means it's an array of variable length. + TypeKindVariableArray ) // Type represents a type specifier @@ -69,8 +69,7 @@ type Type struct { mutable bool kind TypeKind - // only applicable for arrays. a value of zero means it has an - // undefined/dynamic length. + // only applicable for fixed length arrays. length uint64 // only applicable for basic. From 89834ac39097c01a059c85542f22812f7c600920 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 22:30:14 -0400 Subject: [PATCH 14/22] The syntax tree is no longer passed by reference --- parser/parser.go | 6 +++--- parser/test-common.go | 9 --------- parser/tree.go | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index 3a07318..c360b19 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -14,15 +14,15 @@ type ParsingOperation struct { tokens []lexer.Token tokenIndex int - tree *SyntaxTree + tree SyntaxTree } // Parse reads the files located in the module specified by modulePath, and // converts them into an abstract syntax tree. -func Parse (modulePath string) (tree *SyntaxTree, err error) { +func Parse (modulePath string) (tree SyntaxTree, err error) { parser := ParsingOperation { modulePath: modulePath, - tree: &SyntaxTree { + tree: SyntaxTree { sections: make(map[string] Section), }, } diff --git a/parser/test-common.go b/parser/test-common.go index b983534..2784087 100644 --- a/parser/test-common.go +++ b/parser/test-common.go @@ -7,15 +7,6 @@ import "testing" func checkTree (modulePath string, correct string, test *testing.T) { tree, err := Parse(modulePath) - if tree == nil { - test.Log("TREE IS NIL!") - if err != io.EOF && err != nil { - test.Log("returned error:") - test.Log(err) - } - test.Fail() - return - } treeString := tree.ToString(0) treeRunes := []rune(treeString) diff --git a/parser/tree.go b/parser/tree.go index d563942..03a429f 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -44,7 +44,7 @@ type Identifier struct { trail []string } -// TypeKind represents what kind of type a type is +// TypeKind represents what kind of type a type is. type TypeKind int const ( From 3ae8209712075258a652158be95ae3d612b2d404 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 22:40:26 -0400 Subject: [PATCH 15/22] asdjkhaslkjhlkfjhaslkdjhalksjdlksdjalskdj --- parser/parser.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/parser/parser.go b/parser/parser.go index c360b19..215a679 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -17,6 +17,13 @@ type ParsingOperation struct { tree SyntaxTree } +// TODO: +// - implement parser cache +// - have this try to hit the cache, and actually parse on miss +// - rename this to Fetch +// - add `skim bool` argument. when this is true, don't parse any code or data +// section initialization values, just definitions and their default values. + // Parse reads the files located in the module specified by modulePath, and // converts them into an abstract syntax tree. func Parse (modulePath string) (tree SyntaxTree, err error) { From 0cb6b2bf669e98a07587b1696699e8fbb288bc4e Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 23:05:45 -0400 Subject: [PATCH 16/22] Added a generic map iterator type --- types/iterator.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 types/iterator.go diff --git a/types/iterator.go b/types/iterator.go new file mode 100644 index 0000000..0dc72f7 --- /dev/null +++ b/types/iterator.go @@ -0,0 +1,50 @@ +package types + +// Iterator is an object capable of iterating over any string-indexed map, while +// protecting its data. +type Iterator[VALUE_TYPE any] struct { + index int + keys []string + underlying map[string] VALUE_TYPE +} + +// NewIterator creates a new iterator that iterates over the specified map. +func NewIterator[VALUE_TYPE any] ( + underlying map[string] VALUE_TYPE, +) ( + iterator Iterator[VALUE_TYPE], +) { + iterator.underlying = underlying + iterator.keys = make([]string, len(underlying)) + + index := 0 + for key, _ := range underlying { + iterator.keys[index] = key + index ++ + } + + return +} + +// Key returns the current key the iterator is on. +func (iterator Iterator[VALUE_TYPE]) Key () (key string) { + key = iterator.keys[iterator.index] + return +} + +// Value returns the current value the iterator is on. +func (iterator Iterator[VALUE_TYPE]) Value () (value VALUE_TYPE) { + value = iterator.underlying[iterator.keys[iterator.index]] + return +} + +// Next advances the iterator by 1. +func (iterator Iterator[VALUE_TYPE]) Next () { + iterator.index ++ +} + +// AtEnd returns whether the iterator has reached the end of the map. +func (iterator Iterator[VALUE_TYPE]) AtEnd () (atEnd bool) { + atEnd = iterator.index >= len(iterator.keys) || iterator.index < 0 + return +} From 319ed789bf49384b32b787a8d9f9fa59496143e2 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Sun, 4 Sep 2022 23:47:56 -0400 Subject: [PATCH 17/22] Added accessors to ArrayInitializationValues --- parser/accessors.go | 30 +++++++++++++++++++++++++++++- parser/misc.go | 23 +++++++++++++++++++++++ types/iterator.go | 4 ++-- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/parser/accessors.go b/parser/accessors.go index 3a207ce..4c32ea0 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -1,12 +1,20 @@ package parser +import "git.tebibyte.media/arf/arf/types" + // LookupSection looks returns the section under the give name. If the section // does not exist, nil is returned. -func (tree *SyntaxTree) LookupSection (name string) (section Section) { +func (tree SyntaxTree) LookupSection (name string) (section Section) { section = tree.sections[name] return } +// Sections returns an iterator for the tree's sections +func (tree SyntaxTree) Sections () (iterator types.Iterator[Section]) { + iterator = types.NewIterator(tree.sections) + return +} + // Kind returns the section's kind (SectionKindType). func (section TypeSection) Kind () (kind SectionKind) { kind = SectionKindType @@ -93,3 +101,23 @@ func (what Type) Points () (points Type) { } return } + +// Values returns an iterator for the initialization values +func (values ObjectInitializationValues) Sections () ( + iterator types.Iterator[Argument], +) { + iterator = types.NewIterator(values.attributes) + return +} + +// Length returns the amount of values +func (values ArrayInitializationValues) Length () (length int) { + length = len(values.values) + return +} + +// Item returns the value at index +func (values ArrayInitializationValues) Value (index int) (value Argument) { + value = values.values[index] + return +} diff --git a/parser/misc.go b/parser/misc.go index 121df15..9ccc17c 100644 --- a/parser/misc.go +++ b/parser/misc.go @@ -3,6 +3,29 @@ package parser import "git.tebibyte.media/arf/arf/lexer" import "git.tebibyte.media/arf/arf/infoerr" +// TODO: need to come up with another syntax for bitfields, and use that syntax +// for fixed-length arrays. the problem is, we cant use {} for those kinds of +// arrays because they aren't pointers under the hood and that goes against the +// arf design goals in a nasty ugly way, and not only that. but the :mut type +// qualifier is meaningless on fixed length arrays now. the bit field syntax +// solves both of these problems very gracefully. but now, the problem is coming +// up with new bit field syntax. implementing this change is extremely +// necessary, for it will supercharge the coherency of the language and make it +// way more awesome. +// +// this new syntax cannot conflict with arguments, so it cannot have any +// tokens that begin those. basically all symbol tokens are on the table here. +// some ideas: +// +// ro member:Type ~ 4 +// ro member:Type & 4 <- i like this one because binary &. so intuitive. +// ro member:Type % 4 +// ro member:Type | 4 +// ro member:Type ! 4 +// ro member:Type (4) <- this looks phenomenal, but it needs new tokens not +// used anywhere else, and it would be mildly annoying +// to parse. + // parseType parses a type notation of the form Name, {Name}, etc. func (parser *ParsingOperation) parseType () (what Type, err error) { err = parser.expect(lexer.TokenKindName, lexer.TokenKindLBrace) diff --git a/types/iterator.go b/types/iterator.go index 0dc72f7..acc8cc2 100644 --- a/types/iterator.go +++ b/types/iterator.go @@ -43,8 +43,8 @@ func (iterator Iterator[VALUE_TYPE]) Next () { iterator.index ++ } -// AtEnd returns whether the iterator has reached the end of the map. -func (iterator Iterator[VALUE_TYPE]) AtEnd () (atEnd bool) { +// End returns whether the iterator has reached the end of the map. +func (iterator Iterator[VALUE_TYPE]) End () (atEnd bool) { atEnd = iterator.index >= len(iterator.keys) || iterator.index < 0 return } From 88de6f0908b3982bf112ff3ab115c52cccc444c0 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 5 Sep 2022 01:05:03 -0400 Subject: [PATCH 18/22] Added accessors to Argument and ObjtMember --- parser/accessors.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/parser/accessors.go b/parser/accessors.go index 4c32ea0..3b0a51a 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -121,3 +121,23 @@ func (values ArrayInitializationValues) Value (index int) (value Argument) { value = values.values[index] return } + +// Kind returns what kind of argument it is. +func (argument Argument) Kind () (kind ArgumentKind) { + kind = argument.kind + return +} + +// Value returns the underlying value of the argument. You can use Kind() to +// find out what to cast this to. +func (argument Argument) Value () (value any) { + value = argument.value + return +} + +// BitWidth returns the bit width of the object member. If it is zero, it should +// be treated as unspecified. +func (member ObjtMember) BitWidth () (width uint64) { + width = member.bitWidth + return +} From bc4b2bd33c5d0474f20f571c05bb4a4e69c6e734 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 5 Sep 2022 01:09:29 -0400 Subject: [PATCH 19/22] Added accessors for ObjtSection and EnumSection --- parser/accessors.go | 30 +++++++++++++++++++++++++++--- parser/tree.go | 2 +- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/parser/accessors.go b/parser/accessors.go index 3b0a51a..955efdd 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -102,7 +102,7 @@ func (what Type) Points () (points Type) { return } -// Values returns an iterator for the initialization values +// Values returns an iterator for the initialization values. func (values ObjectInitializationValues) Sections () ( iterator types.Iterator[Argument], ) { @@ -110,13 +110,13 @@ func (values ObjectInitializationValues) Sections () ( return } -// Length returns the amount of values +// Length returns the amount of values. func (values ArrayInitializationValues) Length () (length int) { length = len(values.values) return } -// Item returns the value at index +// Item returns the value at index. func (values ArrayInitializationValues) Value (index int) (value Argument) { value = values.values[index] return @@ -141,3 +141,27 @@ func (member ObjtMember) BitWidth () (width uint64) { width = member.bitWidth return } + +// Length returns the amount of members in the section. +func (section ObjtSection) Length () (length int) { + length = len(section.members) + return +} + +// Item returns the member at index. +func (section ObjtSection) Item (index int) (member ObjtMember) { + member = section.members[index] + return +} + +// Length returns the amount of members in the section. +func (section EnumSection) Length () (length int) { + length = len(section.members) + return +} + +// Item returns the member at index. +func (section EnumSection) Item (index int) (member EnumMember) { + member = section.members[index] + return +} diff --git a/parser/tree.go b/parser/tree.go index 03a429f..bb70884 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -193,7 +193,7 @@ type ObjtMember struct { permissionable valuable - bitWidth uint64 + bitWidth uint64 } // ObjtSection represents an object type definition. From caeed943a35ee8f90af4af8e5be91721ff2d35a7 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 5 Sep 2022 01:21:51 -0400 Subject: [PATCH 20/22] Added accessors for FaceSection and FaceBehavior --- parser/accessors.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/parser/accessors.go b/parser/accessors.go index 955efdd..86f2a26 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -165,3 +165,33 @@ func (section EnumSection) Item (index int) (member EnumMember) { member = section.members[index] return } + +// InputsLength returns the amount of inputs in the behavior. +func (behavior FaceBehavior) IntputsLength () (length int) { + length = len(behavior.inputs) + return +} + +// Input returns the input at index. +func (behavior FaceBehavior) Input (index int) (input Declaration) { + input = behavior.inputs[index] + return +} + +// OutputsLength returns the amount of outputs in the behavior. +func (behavior FaceBehavior) OutputsLength () (length int) { + length = len(behavior.outputs) + return +} + +// Output returns the output at index. +func (behavior FaceBehavior) Output (index int) (output Declaration) { + output = behavior.outputs[index] + return +} + +// Behaviors returns an iterator for the interface's behaviors. +func (section FaceSection) Behaviors () (iterator types.Iterator[FaceBehavior]) { + iterator = types.NewIterator(section.behaviors) + return +} From e06de0ad9ab2194832889ea369df772c7c913e4b Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 5 Sep 2022 02:04:37 -0400 Subject: [PATCH 21/22] same thing forf phrases and blocks --- parser/accessors.go | 37 +++++++++++++++++++++++++++++++++++++ parser/tree.go | 4 +++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/parser/accessors.go b/parser/accessors.go index 86f2a26..b3f394e 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -195,3 +195,40 @@ func (section FaceSection) Behaviors () (iterator types.Iterator[FaceBehavior]) iterator = types.NewIterator(section.behaviors) return } + +// Kind returns what kind of phrase it is. +func (phrase Phrase) Kind () (kind PhraseKind) { + kind = phrase.kind + return +} + +// ArgumentsLength returns the amount of arguments in the phrase. +func (phrase Phrase) ArgumentsLength () (length int) { + length = len(phrase.arguments) + return +} + +// Argument returns the argument at index. +func (phrase Phrase) Argument (index int) (argument Argument) { + argument = phrase.arguments[index] + return +} + +// ReturnsToLength returns the amount of things the phrase returns to. +func (phrase Phrase) ReturnsToLength () (length int) { + length = len(phrase.returnsTo) + return +} + +// ReturnTo returns the thing alskdjaslkdjsa whatever i dont even know wtf. +func (phrase Phrase) ReturnTo (index int) (returnTo Argument) { + returnTo = phrase.returnsTo[index] + return +} + +// Block returns the block under the phrase, if it is a control flow statement. +func (phrase Phrase) Block () (block Block) { + block = phrase.block + return +} + diff --git a/parser/tree.go b/parser/tree.go index bb70884..fa47cc9 100644 --- a/parser/tree.go +++ b/parser/tree.go @@ -239,7 +239,7 @@ type FaceSection struct { permissionable inherits Identifier - behaviors map[string] FaceBehavior + behaviors map[string] FaceBehavior } // PhraseKind determines what semantic role a phrase plays. @@ -267,6 +267,8 @@ type Phrase struct { location file.Location command Argument arguments []Argument + // TODO: this is wack. it should be named after a plural noun like, + // returnees or something. accessor methods should beupdated to match. returnsTo []Argument kind PhraseKind From f9187ea58319ddc9691eb63ca6366c055ac14fbb Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Mon, 5 Sep 2022 10:39:46 -0400 Subject: [PATCH 22/22] Created getters for func section --- parser/accessors.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/parser/accessors.go b/parser/accessors.go index b3f394e..28e51d9 100644 --- a/parser/accessors.go +++ b/parser/accessors.go @@ -232,3 +232,45 @@ func (phrase Phrase) Block () (block Block) { return } +// Receiver returns the method receiver, if there is one. Otherwise, it returns +// nil. +func (section FuncSection) Receiver () (receiver *Declaration) { + receiver = section.receiver + return +} + +// InputsLength returns the number of inputs in the function. +func (section FuncSection) InputsLength () (length int) { + length = len(section.inputs) + return +} + +// Input returns the input at index. +func (section FuncSection) Input (index int) (input Declaration) { + input = section.inputs[index] + return +} + +// OutputsLength returns the number of outputs in the function. +func (section FuncSection) OutputsLength () (length int) { + length = len(section.outputs) + return +} + +// Output returns the output at index. +func (section FuncSection) Output (index int) (output FuncOutput) { + output = section.outputs[index] + return +} + +// Root returns the root block of the section. +func (section FuncSection) Root () (root Block) { + root = section.root + return +} + +// External returns whether or not the function is an external function or not. +func (section FuncSection) External () (external bool) { + external = section.external + return +}