Merge pull request 'revert-complexity' (#7) from revert-complexity into main

Reviewed-on: arf/arf#7
This commit is contained in:
Sasha Koshka 2022-09-29 20:06:53 +00:00
commit b2cc45abec
28 changed files with 779 additions and 839 deletions

View File

@ -29,33 +29,49 @@ func (analyzer AnalysisOperation) analyzeArgument (
) {
switch inputArgument.Kind() {
case parser.ArgumentKindNil:
panic (
"invalid state: attempt to analyze nil argument")
case parser.ArgumentKindPhrase:
// TODO
case parser.ArgumentKindDereference:
// TODO
case parser.ArgumentKindSubscript:
// TODO
case parser.ArgumentKindObjectDefaultValues:
// TODO
case parser.ArgumentKindArrayDefaultValues:
// TODO
case parser.ArgumentKindIdentifier:
// TODO
case parser.ArgumentKindDeclaration:
// TODO
case parser.ArgumentKindInt:
outputArgument = IntLiteral(inputArgument.Value().(int64))
case parser.ArgumentKindUInt:
outputArgument = UIntLiteral(inputArgument.Value().(uint64))
case parser.ArgumentKindFloat:
outputArgument = FloatLiteral(inputArgument.Value().(float64))
case parser.ArgumentKindString:
outputArgument = StringLiteral(inputArgument.Value().(string))
case parser.ArgumentKindRune:
outputArgument = RuneLiteral(inputArgument.Value().(rune))
case parser.ArgumentKindOperator:
panic (
"invalid state: attempt to analyze operator argument " +
"directly")
}
return
}

View File

@ -82,22 +82,22 @@ func (what Type) Points () (points Type) {
return
}
// MembersLength returns the amount of new members the type specifier defines.
// MembersLength returns the amount of new members the type section defines.
// If it defines no new members, it returns zero.
func (what Type) MembersLength () (length int) {
length = len(what.members)
func (section TypeSection) MembersLength () (length int) {
length = len(section.members)
return
}
// Member returns the member at index.
func (what Type) Member (index int) (member TypeMember) {
member = what.members[index]
func (section TypeSection) Member (index int) (member TypeSectionMember) {
member = section.members[index]
return
}
// BitWidth returns the bit width of the type member. If it is zero, it should
// be treated as unspecified.
func (member TypeMember) BitWidth () (width uint64) {
func (member TypeSectionMember) BitWidth () (width uint64) {
width = member.bitWidth
return
}
@ -169,18 +169,6 @@ func (phrase Phrase) Kind () (kind PhraseKind) {
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
}
// ReturneesLength returns the amount of things the phrase returns to.
func (phrase Phrase) ReturneesLength () (length int) {
length = len(phrase.returnees)

View File

@ -3,6 +3,8 @@ package parser
import "git.tebibyte.media/arf/arf/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
// TODO: add support for dereferences and subscripts
var validArgumentStartTokens = []lexer.TokenKind {
lexer.TokenKindName,
@ -13,6 +15,7 @@ var validArgumentStartTokens = []lexer.TokenKind {
lexer.TokenKindRune,
lexer.TokenKindLBracket,
lexer.TokenKindLParen,
}
func (parser *ParsingOperation) parseArgument () (argument Argument, err error) {
@ -84,6 +87,10 @@ func (parser *ParsingOperation) parseArgument () (argument Argument, err error)
argument.kind = ArgumentKindPhrase
argument.value, err = parser.parseArgumentLevelPhrase()
case lexer.TokenKindLParen:
argument.kind = ArgumentKindList
argument.value, err = parser.parseList()
default:
panic (
"unimplemented argument kind " +

View File

@ -35,28 +35,37 @@ func (parser *ParsingOperation) parseDataSection () (
return
}
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
// check if data is external
if parser.token.Is(lexer.TokenKindIndent) &&
parser.token.Value().(int) == 1 {
// see if value exists
if parser.token.Is(lexer.TokenKindNewline) {
parser.nextToken()
// if we have exited the section, return
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 1 { return }
err = parser.nextToken(lexer.TokenKindName)
err = parser.nextToken()
if err != nil { return }
}
// check if external
if parser.token.Is(lexer.TokenKindName) {
if parser.token.Value().(string) == "external" {
section.external = true
err = parser.nextToken(lexer.TokenKindNewline)
if err != nil { return }
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
return
}
parser.previousToken()
}
// get value
section.argument, err = parser.parseArgument()
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
return
}

View File

@ -6,14 +6,16 @@ func TestData (test *testing.T) {
checkTree ("../tests/parser/data", false,
`:arf
---
data ro aInteger:Int:<3202>
data ro bMutInteger:Int:mut:<3202>
data ro aInteger:Int
3202
data ro bMutInteger:Int:mut
3202
data ro cIntegerPointer:{Int}
data ro dMutIntegerPointer:{Int}:mut
data ro eIntegerArray16:Int:16
data ro fIntegerArrayVariable:{Int ..}
data ro gIntegerArrayInitialized:Int:16:
<
data ro gIntegerArrayInitialized:Int:16
(
3948
293
293049
@ -25,35 +27,21 @@ data ro gIntegerArrayInitialized:Int:16:
0
4785
92
>
data rw hIntegerPointerInit:{Int}:<[& integer]>
data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]>
data ro jObject:Obj:
(
.that:<324>
.this:<324>
)
data ro kNestedObject:Obj:
data rw hIntegerPointerInit:{Int}
[& integer]
data rw iMutIntegerPointerInit:{Int}:mut
[& integer]
data ro jObject:Obj
(
.ro newMember:Int:<9023>
):
(
.that:
(
.bird2:<123.8439>
.bird3:<9328.21348239>
)
.this:
(
.bird0:<324>
.bird1:<"hello world">
)
324
438
)
data ro lMutIntegerArray16:Int:16:mut
data ro mExternalData:Int:8
external
data ro nIntegerArrayInitialized:Int:16:mut:
<
data ro nIntegerArrayInitialized:Int:16:mut
(
3948
293
293049
@ -65,6 +53,6 @@ data ro nIntegerArrayInitialized:Int:16:mut:
0
4785
92
>
)
`, test)
}

View File

@ -61,18 +61,11 @@ func (parser *ParsingOperation) parseEnumMembers (
// if we've left the block, stop parsing
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 1 { return }
err = parser.nextToken(lexer.TokenKindMinus)
if err != nil { return }
var member EnumMember
member, err = parser.parseEnumMember()
into.members = append(into.members, member)
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
}
}
@ -81,7 +74,7 @@ func (parser *ParsingOperation) parseEnumMember () (
member EnumMember,
err error,
) {
err = parser.expect(lexer.TokenKindMinus)
err = parser.nextToken(lexer.TokenKindMinus)
if err != nil { return }
// get name
@ -91,32 +84,25 @@ func (parser *ParsingOperation) parseEnumMember () (
member.name = parser.token.Value().(string)
// see if value exists
err = parser.nextToken (
lexer.TokenKindColon,
lexer.TokenKindNewline)
err = parser.nextToken()
if err != nil { return }
if parser.token.Is(lexer.TokenKindColon) {
if parser.token.Is(lexer.TokenKindNewline) {
parser.nextToken()
// if we have exited the member, return
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 2 { return }
err = parser.nextToken()
if err != nil { return }
err = parser.skipWhitespace()
if err != nil { return }
err = parser.expect (
lexer.TokenKindLessThan,
lexer.TokenKindLParen)
if err != nil { return }
if parser.token.Is(lexer.TokenKindLessThan) {
// parse value
member.value, err = parser.parseBasicDefaultValue()
if err != nil { return }
} else if parser.token.Is(lexer.TokenKindLParen) {
// parse default values
member.value, err = parser.parseObjectDefaultValue()
if err != nil { return }
}
}
// get value
member.argument, err = parser.parseArgument()
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
return
}

View File

@ -7,56 +7,18 @@ func TestEnum (test *testing.T) {
`:arf
---
enum ro AffrontToGod:Int:4
- bird0:
<
28394
9328
398
9
>
- bird1:
<
23
932832
398
2349
>
- bird2:
<
1
2
3
4
>
- bird0 (28394 9328 398 9)
- bird1 (23 932832 398 2349)
- bird2 (1 2 3 4)
enum ro NamedColor:U32
- red:<16711680>
- green:<65280>
- blue:<255>
enum ro ThisIsTerrible:Obj:
(
.rw x:Int
.rw y:Int
)
- up:
(
.x:<0>
.y:<-1>
)
- down:
(
.x:<0>
.y:<1>
)
- left:
(
.x:<-1>
.y:<0>
)
- right:
(
.x:<1>
.y:<0>
)
- red 16711680
- green 65280
- blue 255
enum ro ThisIsTerrible:Vector
- up (0 -1)
- down (0 1)
- left (-1 0)
- right (1 0)
enum ro Weekday:Int
- sunday
- monday

View File

@ -12,8 +12,7 @@ func (parser *ParsingOperation) parseFaceSection () (
err = parser.expect(lexer.TokenKindName)
if err != nil { return }
section.behaviors = make(map[string] FaceBehavior)
section.location = parser.token.Location()
section.location = parser.token.Location()
// get permission
err = parser.nextToken(lexer.TokenKindPermission)
@ -32,24 +31,61 @@ func (parser *ParsingOperation) parseFaceSection () (
if err != nil { return }
section.inherits, err = parser.parseIdentifier()
if err != nil { return }
err = parser.nextToken(lexer.TokenKindNewline)
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 1 { return }
err = parser.nextToken (
lexer.TokenKindName,
lexer.TokenKindGreaterThan,
lexer.TokenKindLessThan)
if err != nil { return }
if parser.token.Is(lexer.TokenKindName) {
// parse type interface
section.kind = FaceKindType
parser.previousToken()
section.behaviors, err = parser.parseFaceBehaviors()
if err != nil { return }
} else {
// parse function interface
section.kind = FaceKindFunc
parser.previousToken()
section.inputs,
section.outputs, err = parser.parseFaceBehaviorArguments(1)
if err != nil { return }
}
return
}
// parseFaceBehaviors parses a list of interface behaviors for an object
// interface.
func (parser *ParsingOperation) parseFaceBehaviors () (
behaviors map[string] FaceBehavior,
err error,
) {
// parse members
behaviors = make(map[string] FaceBehavior)
for {
// if we've left the block, stop parsing
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 1 { return }
err = parser.nextToken(lexer.TokenKindName)
behaviorBeginning := parser.token.Location()
if err != nil { return }
// parse behavior
behaviorBeginning := parser.token.Location()
var behavior FaceBehavior
behavior, err = parser.parseFaceBehavior()
behavior, err = parser.parseFaceBehavior(1)
// add to section
_, exists := section.behaviors[behavior.name]
_, exists := behaviors[behavior.name]
if exists {
err = infoerr.NewError (
behaviorBeginning,
@ -58,23 +94,21 @@ func (parser *ParsingOperation) parseFaceSection () (
infoerr.ErrorKindError)
return
}
section.behaviors[behavior.name] = behavior
behaviors[behavior.name] = behavior
if err != nil { return }
}
}
// parseFaceBehavior parses a single interface behavior. Indentation level is
// assumed.
func (parser *ParsingOperation) parseFaceBehavior () (
// parseFaceBehavior parses a single interface behavior.
func (parser *ParsingOperation) parseFaceBehavior (
indent int,
) (
behavior FaceBehavior,
err error,
) {
err = parser.expect(lexer.TokenKindIndent)
if err != nil { return }
// get name
err = parser.nextToken(lexer.TokenKindName)
err = parser.expect(lexer.TokenKindName)
if err != nil { return }
behavior.name = parser.token.Value().(string)
@ -82,11 +116,27 @@ func (parser *ParsingOperation) parseFaceBehavior () (
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
behavior.inputs,
behavior.outputs,
err = parser.parseFaceBehaviorArguments(indent + 1)
if err != nil { return }
return
}
func (parser *ParsingOperation) parseFaceBehaviorArguments (
indent int,
) (
inputs []Declaration,
outputs []Declaration,
err error,
) {
for {
// if we've left the block, stop parsing
// if we've left the behavior, stop parsing
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 2 { return }
if parser.token.Value().(int) != indent { return }
// get preceding symbol
err = parser.nextToken (
@ -109,19 +159,16 @@ func (parser *ParsingOperation) parseFaceBehavior () (
if err != nil { return }
declaration.what, err = parser.parseType()
if err != nil { return }
if kind == lexer.TokenKindGreaterThan {
inputs = append(inputs, declaration)
} else {
outputs = append(outputs, declaration)
}
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
if kind == lexer.TokenKindGreaterThan {
behavior.inputs = append (
behavior.inputs,
declaration)
} else {
behavior.outputs = append (
behavior.outputs,
declaration)
}
}
}

25
parser/face_test.go Normal file
View File

@ -0,0 +1,25 @@
package parser
import "testing"
func TestFace (test *testing.T) {
checkTree ("../tests/parser/face", false,
`:arf
---
face ro aReadWriter:Face
read
> into:{Byte ..}
< read:Int
< err:Error
write
> data:{Byte ..}
< wrote:Int
< err:Error
face ro bDestroyer:Face
destroy
face ro cFuncInterface:Func
> something:Int
< someOutput:Int
< otherOutput:String
`, test)
}

View File

@ -171,7 +171,7 @@ func (parser *ParsingOperation) parseFuncArguments (
if err != nil { return }
case lexer.TokenKindLessThan:
output := Declaration { }
output := FuncOutput { }
output.location = parser.token.Location()
// get name
@ -186,11 +186,32 @@ func (parser *ParsingOperation) parseFuncArguments (
if err != nil { return }
output.what, err = parser.parseType()
if err != nil { return }
into.outputs = append(into.outputs, output)
parser.expect(lexer.TokenKindNewline)
// skip newline if it is there
if parser.token.Is(lexer.TokenKindNewline) {
parser.nextToken()
// if we have exited the output, break
exited :=
!parser.token.Is(lexer.TokenKindIndent) ||
parser.token.Value().(int) != 2
if exited {
into.outputs = append(into.outputs, output)
break
}
err = parser.nextToken()
if err != nil { return }
}
// get default value
output.argument, err = parser.parseArgument()
into.outputs = append(into.outputs, output)
if err != nil { return }
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
}

View File

@ -8,13 +8,13 @@ func TestFunc (test *testing.T) {
---
func ro aBasicExternal
> someInput:Int:mut
< someOutput:Int:<4>
< someOutput:Int 4
---
external
func ro bMethod
@ bird:{Bird}
> someInput:Int:mut
< someOutput:Int:<4>
< someOutput:Int 4
---
external
func ro cBasicPhrases
@ -99,11 +99,11 @@ func ro gControlFlow
[nestedThing]
[else]
[otherThing]
func ro hSetPhrase
func ro hDataInit
---
[let x:Int:<3>]
[let y:{Int}:<[loc x]>]
[let z:Int:8:<398 9 2309 983 -2387 478 555 123>]
[let bird:Bird:(.that:(.whenYou:<99999>) .this:<324>)]
[= x:Int 3]
[= y:{Int} [loc x]]
[= z:Int:8 (398 9 2309 983 -2387 478 555 123)]
[= bird:Bird ((99999) 324)]
`, test)
}

32
parser/list.go Normal file
View File

@ -0,0 +1,32 @@
package parser
import "git.tebibyte.media/arf/arf/lexer"
// parseList parses a parenthetically delimited list of arguments.
func (parser *ParsingOperation) parseList () (list List, err error) {
list.location = parser.token.Location()
err = parser.expect(lexer.TokenKindLParen)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
for {
err = parser.skipWhitespace()
if err != nil { return }
// if we have reached the end of the list, stop
if parser.token.Is(lexer.TokenKindRParen) { break }
// otherwise, parse argument
var argument Argument
argument, err = parser.parseArgument()
list.arguments = append(list.arguments, argument)
if err != nil { return }
}
err = parser.nextToken()
if err != nil { return }
return
}

View File

@ -11,8 +11,8 @@ func TestMeta (test *testing.T) {
author "Sasha Koshka"
license "GPLv3"
require "` + filepath.Join(cwd, "./some/local/module") + `"
require "/some/absolute/path/to/someModule"
require "/usr/local/include/arf/someLibraryInstalledInStandardLocation"
require "/some/absolute/path/to/someModule"
---
`, test)
}

View File

@ -10,19 +10,19 @@ type locatable struct {
}
// Location returns the location of the node.
func (trait locatable) Location () (location file.Location) {
location = trait.location
func (node locatable) Location () (location file.Location) {
location = node.location
return
}
// NewError creates a new error at the node's location.
func (trait locatable) NewError (
func (node locatable) NewError (
message string,
kind infoerr.ErrorKind,
) (
err error,
) {
err = infoerr.NewError(trait.location, message, kind)
err = infoerr.NewError(node.location, message, kind)
return
}
@ -32,8 +32,8 @@ type nameable struct {
}
// Name returns the name of the node.
func (trait nameable) Name () (name string) {
name = trait.name
func (node nameable) Name () (name string) {
name = node.name
return
}
// typeable allows a node to have a type.
@ -42,8 +42,8 @@ type typeable struct {
}
// Type returns the type of the node.
func (trait typeable) Type () (what Type) {
what = trait.what
func (node typeable) Type () (what Type) {
what = node.what
return
}
@ -53,18 +53,35 @@ type permissionable struct {
}
// Permission returns the permision of the node.
func (trait permissionable) Permission () (permission types.Permission) {
permission = trait.permission
func (node permissionable) Permission () (permission types.Permission) {
permission = node.permission
return
}
// valuable allows a node to have an argument value.
type valuable struct {
value Argument
argument Argument
}
// Value returns the value argument of the node.
func (trait valuable) Value () (value Argument) {
value = trait.value
// Argument returns the value argument of the node.
func (node valuable) Argument () (argument Argument) {
argument = node.argument
return
}
// multiValuable allows a node to have several argument values.
type multiValuable struct {
arguments []Argument
}
// Argument returns the argument at index.
func (node multiValuable) Argument (index int) (argument Argument) {
argument = node.arguments[index]
return
}
// Length returns the amount of arguments in the mode.
func (node multiValuable) Length () (length int) {
length = len(node.arguments)
return
}

View File

@ -150,16 +150,35 @@ func (parser *ParsingOperation) previousToken () {
// skipIndentLevel advances the parser, ignoring every line with an indentation
// equal to or greater than the specified indent.
func (parser *ParsingOperation) skipIndentLevel (indent int) (err error) {
braceLevel := 0
parenLevel := 0
bracketLevel := 0
for {
if parser.token.Is(lexer.TokenKindNewline) {
err = parser.nextToken()
if err != nil { return }
if !parser.token.Is(lexer.TokenKindIndent) ||
parser.token.Value().(int) < indent {
shouldBreak :=
!parser.token.Is(lexer.TokenKindIndent) ||
parser.token.Value().(int) < indent
shouldBreak =
shouldBreak &&
braceLevel < 1 &&
parenLevel < 1 &&
bracketLevel < 1
return
}
if shouldBreak { return }
}
switch parser.token.Kind() {
case lexer.TokenKindLBrace: braceLevel ++
case lexer.TokenKindRBrace: braceLevel --
case lexer.TokenKindLParen: parenLevel ++
case lexer.TokenKindRParen: parenLevel --
case lexer.TokenKindLBracket: bracketLevel ++
case lexer.TokenKindRBracket: bracketLevel --
}
err = parser.nextToken()

View File

@ -129,7 +129,10 @@ func (parser *ParsingOperation) parseBlockLevelPhrase (
// get command
err = parser.expect(validPhraseStartTokens...)
if err != nil { return }
phrase.command, phrase.kind, err = parser.parsePhraseCommand()
phrase.command,
phrase.kind,
phrase.operator,
err = parser.parsePhraseCommand()
if err != nil { return }
for {
@ -233,7 +236,10 @@ func (parser *ParsingOperation) parseArgumentLevelPhrase () (
// get command
err = parser.nextToken(validPhraseStartTokens...)
if err != nil { return }
phrase.command, phrase.kind, err = parser.parsePhraseCommand()
phrase.command,
phrase.kind,
phrase.operator,
err = parser.parsePhraseCommand()
if err != nil { return }
for {
@ -272,24 +278,22 @@ func (parser *ParsingOperation) parseArgumentLevelPhrase () (
// parsePhraseCommand parses the command argument of a phrase.
func (parser *ParsingOperation) parsePhraseCommand () (
command Argument,
kind PhraseKind,
err error,
command Argument,
kind PhraseKind,
operator lexer.TokenKind,
err error,
) {
if isTokenOperator(parser.token) {
err = parser.expect(operatorTokens...)
if err != nil { return }
command.location = parser.token.Location()
command.kind = ArgumentKindOperator
command.value = parser.token.Kind()
if parser.token.Is(lexer.TokenKindColon) {
kind = PhraseKindCase
} else if parser.token.Is(lexer.TokenKindAssignment) {
kind = PhraseKindAssign
} else {
kind = PhraseKindOperator
operator = parser.token.Kind()
}
err = parser.nextToken()
@ -308,8 +312,6 @@ func (parser *ParsingOperation) parsePhraseCommand () (
identifier := command.value.(Identifier)
if len(identifier.trail) == 1 {
switch identifier.trail[0] {
case "let":
kind = PhraseKindLet
case "loc":
kind = PhraseKindReference
case "defer":

View File

@ -21,7 +21,7 @@ func ro fComplexFunction
external
func ro gExternalFunction
> x:Int
< arr:Int
< arr:Int 5
---
external
`, test)

View File

@ -41,7 +41,8 @@ func (tree SyntaxTree) ToString (indent int) (output string) {
output += doIndent(indent, "license \"", tree.license, "\"\n")
}
for _, require := range tree.requires {
for _, name := range sortMapKeysAlphabetically(tree.requires) {
require := tree.requires[name]
output += doIndent(indent, "require \"", require, "\"\n")
}
@ -66,84 +67,17 @@ func (identifier Identifier) ToString () (output string) {
return
}
func (values ObjectDefaultValues) ToString (
indent int,
breakLine bool,
) (
output string,
) {
if !breakLine { indent = 0 }
output += doIndent(indent, "(")
if breakLine { output += "\n" }
for index, name := range sortMapKeysAlphabetically(values) {
if index > 0 && !breakLine { output += " " }
value := values[name]
output += doIndent(indent, "." + name + ":")
isComplexDefaultValue :=
value.kind == ArgumentKindObjectDefaultValues ||
value.kind == ArgumentKindArrayDefaultValues
if isComplexDefaultValue {
if breakLine { output += "\n" }
output += value.ToString(indent + 1, breakLine)
} else {
output += "<"
output += value.ToString(indent + 1, false)
output += ">"
}
if breakLine { output += "\n" }
}
output += doIndent(indent, ")")
return
}
func (values ArrayDefaultValues) ToString (
indent int,
breakLine bool,
) (
output string,
) {
if !breakLine { indent = 0 }
output += doIndent(indent, "<")
if breakLine { output += "\n" }
for index, value := range values {
if index > 0 && !breakLine { output += " " }
output += value.ToString(indent, breakLine)
}
output += doIndent(indent, ">")
return
}
func (member TypeMember) ToString (indent int, breakLine bool) (output string) {
output += doIndent(indent, ".")
output += member.permission.ToString() + " "
output += member.name + ":"
output += member.what.ToString(indent + 1, breakLine)
if member.bitWidth > 0 {
output += fmt.Sprint(" & ", member.bitWidth)
func (what Type) ToString () (output string) {
if what.kind == TypeKindNil {
output += "NIL-TYPE"
return
}
if breakLine {
output += "\n"
}
return
}
func (what Type) ToString (indent int, breakLine bool) (output string) {
if what.kind == TypeKindBasic {
output += what.name.ToString()
} else {
output += "{"
output += what.points.ToString(indent, breakLine)
output += what.points.ToString()
if what.kind == TypeKindVariableArray {
output += " .."
@ -159,46 +93,27 @@ func (what Type) ToString (indent int, breakLine bool) (output string) {
if what.mutable {
output += ":mut"
}
if what.members != nil {
if breakLine {
output += ":\n" + doIndent(indent, "(\n")
for _, member := range what.members {
output += member.ToString(indent, breakLine)
}
output += doIndent(indent, ")")
} else {
output += ":("
for index, member := range what.members {
if index > 0 { output += " " }
output += member.ToString(indent, breakLine)
}
output += ")"
}
}
defaultValueKind := what.defaultValue.kind
if defaultValueKind != ArgumentKindNil {
isComplexDefaultValue :=
defaultValueKind == ArgumentKindObjectDefaultValues ||
defaultValueKind == ArgumentKindArrayDefaultValues
if isComplexDefaultValue {
output += ":"
if breakLine { output += "\n" }
output += what.defaultValue.ToString(indent, breakLine)
} else {
output += ":<"
output += what.defaultValue.ToString(indent, false)
output += ">"
}
}
return
}
func (declaration Declaration) ToString (indent int) (output string) {
func (declaration Declaration) ToString () (output string) {
output += declaration.name + ":"
output += declaration.what.ToString(indent, false)
output += declaration.what.ToString()
return
}
func (list List) ToString (indent int, breakline bool) (output string) {
if !breakline { indent = 0 }
output += doIndent(indent, "(")
if breakline { output += "\n" }
for index, argument := range list.arguments {
if !breakline && index > 0 { output += " "}
output += argument.ToString(indent, breakline)
}
output += doIndent(indent, ")")
if breakline { output += "\n" }
return
}
@ -216,13 +131,8 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
indent,
breakLine)
case ArgumentKindObjectDefaultValues:
output += argument.value.(ObjectDefaultValues).
ToString(indent, breakLine)
case ArgumentKindArrayDefaultValues:
output += argument.value.(ArrayDefaultValues).
ToString(indent, breakLine)
case ArgumentKindList:
output += argument.value.(List).ToString(indent, breakLine)
case ArgumentKindIdentifier:
output += doIndent (
@ -233,7 +143,7 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
case ArgumentKindDeclaration:
output += doIndent (
indent,
argument.value.(Declaration).ToString(indent))
argument.value.(Declaration).ToString())
if breakLine { output += "\n" }
case ArgumentKindInt, ArgumentKindUInt, ArgumentKindFloat:
@ -251,75 +161,6 @@ func (argument Argument) ToString (indent int, breakLine bool) (output string) {
indent,
"'" + string(argument.value.(rune)) + "'")
if breakLine { output += "\n" }
case ArgumentKindOperator:
var stringValue string
switch argument.value.(lexer.TokenKind) {
case lexer.TokenKindColon:
stringValue = ":"
case lexer.TokenKindPlus:
stringValue = "+"
case lexer.TokenKindMinus:
stringValue = "-"
case lexer.TokenKindIncrement:
stringValue = "++"
case lexer.TokenKindDecrement:
stringValue = "--"
case lexer.TokenKindAsterisk:
stringValue = "*"
case lexer.TokenKindSlash:
stringValue = "/"
case lexer.TokenKindExclamation:
stringValue = "!"
case lexer.TokenKindPercent:
stringValue = "%"
case lexer.TokenKindPercentAssignment:
stringValue = "%="
case lexer.TokenKindTilde:
stringValue = "~"
case lexer.TokenKindTildeAssignment:
stringValue = "~="
case lexer.TokenKindAssignment:
stringValue = "="
case lexer.TokenKindEqualTo:
stringValue = "=="
case lexer.TokenKindNotEqualTo:
stringValue = "!="
case lexer.TokenKindLessThanEqualTo:
stringValue = "<="
case lexer.TokenKindLessThan:
stringValue = "<"
case lexer.TokenKindLShift:
stringValue = "<<"
case lexer.TokenKindLShiftAssignment:
stringValue = "<<="
case lexer.TokenKindGreaterThan:
stringValue = ">"
case lexer.TokenKindGreaterThanEqualTo:
stringValue = ">="
case lexer.TokenKindRShift:
stringValue = ">>"
case lexer.TokenKindRShiftAssignment:
stringValue = ">>="
case lexer.TokenKindBinaryOr:
stringValue = "|"
case lexer.TokenKindBinaryOrAssignment:
stringValue = "|="
case lexer.TokenKindLogicalOr:
stringValue = "||"
case lexer.TokenKindBinaryAnd:
stringValue = "&"
case lexer.TokenKindBinaryAndAssignment:
stringValue = "&="
case lexer.TokenKindLogicalAnd:
stringValue = "&&"
case lexer.TokenKindBinaryXor:
stringValue = "^"
case lexer.TokenKindBinaryXorAssignment:
stringValue = "^="
}
output += doIndent(indent, stringValue)
if breakLine { output += "\n" }
}
return
@ -331,7 +172,11 @@ func (section DataSection) ToString (indent int) (output string) {
"data ",
section.permission.ToString(), " ",
section.name, ":",
section.what.ToString(indent + 1, true), "\n")
section.what.ToString(), "\n")
if section.argument.kind != ArgumentKindNil {
output += section.argument.ToString(indent + 1, true)
}
if section.external {
output += doIndent(indent + 1, "external\n")
@ -340,37 +185,57 @@ func (section DataSection) ToString (indent int) (output string) {
return
}
func (member TypeSectionMember) ToString (indent int) (output string) {
output += doIndent(indent, member.permission.ToString())
output += " " + member.name
if member.what.kind != TypeKindNil {
output += ":" + member.what.ToString()
}
if member.argument.kind != ArgumentKindNil {
output += " " + member.argument.ToString(indent, false)
}
if member.bitWidth > 0 {
output += fmt.Sprint(" & ", member.bitWidth)
}
output += "\n"
return
}
func (section TypeSection) ToString (indent int) (output string) {
output += doIndent (
indent,
"type ",
section.permission.ToString(), " ",
section.name, ":",
section.what.ToString(indent + 1, true), "\n")
section.what.ToString(), "\n")
if section.argument.kind != ArgumentKindNil {
output += section.argument.ToString(indent + 1, true)
}
for _, member := range section.members {
output += member.ToString(indent + 1)
}
return
}
func (section EnumSection) ToString (indent int) (output string) {
output += doIndent (
indent,
"enum ",
section.permission.ToString(), " ",
section.name, ":",
section.what.ToString(indent + 1, true), "\n")
section.what.ToString(), "\n")
for _, member := range section.members {
output += doIndent(indent + 1, "- ", member.name)
isComplexInitialization :=
member.value.kind == ArgumentKindObjectDefaultValues ||
member.value.kind == ArgumentKindArrayDefaultValues
if isComplexInitialization {
output += ":\n"
output += member.value.ToString(indent + 2, true)
} else if member.value.kind != ArgumentKindNil {
output += ":<" + member.value.ToString(0, false) + ">"
if member.argument.kind != ArgumentKindNil {
output += " " + member.argument.ToString(indent, false)
}
output += "\n"
}
@ -385,10 +250,21 @@ func (section FaceSection) ToString (indent int) (output string) {
section.name, ":",
section.inherits.ToString(), "\n")
for _, name := range sortMapKeysAlphabetically(section.behaviors) {
behavior := section.behaviors[name]
output += behavior.ToString(indent + 1)
if section.kind == FaceKindType {
for _, name := range sortMapKeysAlphabetically(section.behaviors) {
behavior := section.behaviors[name]
output += behavior.ToString(indent + 1)
}
} else if section.kind == FaceKindFunc {
for _, inputItem := range section.inputs {
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
}
for _, outputItem := range section.outputs {
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
}
}
return
}
@ -396,11 +272,11 @@ func (behavior FaceBehavior) ToString (indent int) (output string) {
output += doIndent(indent, behavior.name, "\n")
for _, inputItem := range behavior.inputs {
output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n")
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
}
for _, outputItem := range behavior.outputs {
output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n")
output += doIndent(indent + 1, "< ", outputItem.ToString(), "\n")
}
return
@ -411,7 +287,86 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
output += doIndent(indent)
}
output += "[" + phrase.command.ToString(0, false)
output += "["
switch phrase.kind {
case PhraseKindCase:
output += ":"
case PhraseKindAssign:
output += "="
case PhraseKindOperator:
switch phrase.operator {
case lexer.TokenKindColon:
output += ":"
case lexer.TokenKindPlus:
output += "+"
case lexer.TokenKindMinus:
output += "-"
case lexer.TokenKindIncrement:
output += "++"
case lexer.TokenKindDecrement:
output += "--"
case lexer.TokenKindAsterisk:
output += "*"
case lexer.TokenKindSlash:
output += "/"
case lexer.TokenKindExclamation:
output += "!"
case lexer.TokenKindPercent:
output += "%"
case lexer.TokenKindPercentAssignment:
output += "%="
case lexer.TokenKindTilde:
output += "~"
case lexer.TokenKindTildeAssignment:
output += "~="
case lexer.TokenKindAssignment:
output += "="
case lexer.TokenKindEqualTo:
output += "=="
case lexer.TokenKindNotEqualTo:
output += "!="
case lexer.TokenKindLessThanEqualTo:
output += "<="
case lexer.TokenKindLessThan:
output += "<"
case lexer.TokenKindLShift:
output += "<<"
case lexer.TokenKindLShiftAssignment:
output += "<<="
case lexer.TokenKindGreaterThan:
output += ">"
case lexer.TokenKindGreaterThanEqualTo:
output += ">="
case lexer.TokenKindRShift:
output += ">>"
case lexer.TokenKindRShiftAssignment:
output += ">>="
case lexer.TokenKindBinaryOr:
output += "|"
case lexer.TokenKindBinaryOrAssignment:
output += "|="
case lexer.TokenKindLogicalOr:
output += "||"
case lexer.TokenKindBinaryAnd:
output += "&"
case lexer.TokenKindBinaryAndAssignment:
output += "&="
case lexer.TokenKindLogicalAnd:
output += "&&"
case lexer.TokenKindBinaryXor:
output += "^"
case lexer.TokenKindBinaryXorAssignment:
output += "^="
}
default:
output += phrase.command.ToString(0, false)
}
for _, argument := range phrase.arguments {
output += " " + argument.ToString(0, false)
}
@ -433,6 +388,17 @@ func (phrase Phrase) ToString (indent int, ownLine bool) (output string) {
return
}
func (funcOutput FuncOutput) ToString (indent int) (output string) {
output += doIndent(indent + 1)
output += "< " + funcOutput.Declaration.ToString()
if funcOutput.argument.kind != ArgumentKindNil {
output += " " + funcOutput.argument.ToString(indent, false)
}
output += "\n"
return
}
func (block Block) ToString (indent int) (output string) {
for _, phrase := range block {
output += phrase.ToString(indent, true)
@ -451,15 +417,15 @@ func (section FuncSection) ToString (indent int) (output string) {
if section.receiver != nil {
output += doIndent (
indent + 1,
"@ ", section.receiver.ToString(indent), "\n")
"@ ", section.receiver.ToString(), "\n")
}
for _, inputItem := range section.inputs {
output += doIndent(indent + 1, "> ", inputItem.ToString(indent), "\n")
output += doIndent(indent + 1, "> ", inputItem.ToString(), "\n")
}
for _, outputItem := range section.outputs {
output += doIndent(indent + 1, "< ", outputItem.ToString(indent), "\n")
output += outputItem.ToString(indent)
}
output += doIndent(indent + 1, "---\n")

View File

@ -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/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
// SyntaxTree represents an abstract syntax tree. It covers an entire module. It
@ -35,9 +36,12 @@ type Identifier struct {
type TypeKind int
const (
// TypeKindNil means that the type is unspecified.
TypeKindNil TypeKind = iota
// TypeKindBasic means its a normal type and inherits from something.
// Basic types can define new members on their parent types.
TypeKindBasic TypeKind = iota
TypeKindBasic
// TypeKindPointer means it's a pointer.
TypeKindPointer
@ -46,16 +50,6 @@ const (
TypeKindVariableArray
)
// TypeMember represents a member variable of a type specifier.
type TypeMember struct {
locatable
nameable
typeable
permissionable
bitWidth uint64
}
// Type represents a type specifier
type Type struct {
locatable
@ -69,12 +63,6 @@ type Type struct {
// not applicable for basic.
points *Type
// if non-nil, this type defines new members.
members []TypeMember
// the default value of the type.
defaultValue Argument
}
// Declaration represents a variable declaration.
@ -84,12 +72,14 @@ type Declaration struct {
typeable
}
// ObjectDefaultValues represents a list of object member initialization
// attributes.
type ObjectDefaultValues map[string] Argument
// List represents an array or object literal.
type List struct {
locatable
// ArrayDefaultValues represents a list of elements initializing an array.
type ArrayDefaultValues []Argument
// TODO: have an array of unnamed arguments, and a map of named
// arguments
multiValuable
}
// ArgumentKind specifies the type of thing the value of an argument should be
// cast to.
@ -103,19 +93,15 @@ const (
// etc...
ArgumentKindPhrase
// (argument argument argument)
ArgumentKindList
// {name}
ArgumentKindDereference
// {name 23}
ArgumentKindSubscript
// (.name <value>)
// (.name <value> .name (.name <value))
ArgumentKindObjectDefaultValues
// <4 32 98 5>
ArgumentKindArrayDefaultValues
// name.name
// name.name.name
// etc...
@ -142,10 +128,6 @@ const (
// 'S'
ArgumentKindRune
// + - * / etc...
// this is only used as a phrase command
ArgumentKindOperator
)
// Argument represents a value that can be placed anywhere a value goes. This
@ -164,16 +146,32 @@ type DataSection struct {
nameable
typeable
permissionable
valuable
external bool
}
// TypeSectionMember represents a member variable of a type section.
type TypeSectionMember struct {
locatable
nameable
typeable
permissionable
valuable
bitWidth uint64
}
// TypeSection represents a type definition.
type TypeSection struct {
locatable
nameable
typeable
permissionable
valuable
// if non-nil, this type defines new members.
members []TypeSectionMember
}
// EnumMember represents a member of an enum section.
@ -193,6 +191,16 @@ type EnumSection struct {
members []EnumMember
}
// FaceKind determines if an interface is a type interface or an function
// interface.
type FaceKind int
const (
FaceKindEmpty FaceKind = iota
FaceKindType
FaceKindFunc
)
// FaceBehavior represents a behavior of an interface section.
type FaceBehavior struct {
locatable
@ -208,8 +216,11 @@ type FaceSection struct {
nameable
permissionable
inherits Identifier
kind FaceKind
behaviors map[string] FaceBehavior
FaceBehavior
}
// PhraseKind determines what semantic role a phrase plays.
@ -219,7 +230,6 @@ const (
PhraseKindCall = iota
PhraseKindCallExternal
PhraseKindOperator
PhraseKindLet
PhraseKindAssign
PhraseKindReference
PhraseKindDefer
@ -236,12 +246,18 @@ const (
// syntactical concept.
type Phrase struct {
location file.Location
command Argument
arguments []Argument
returnees []Argument
multiValuable
kind PhraseKind
// TODO: do not have this be an argument. make a string version, and
// and identifier version.
command Argument
// only applicable for PhraseKindOperator
operator lexer.TokenKind
// only applicable for control flow phrases
block Block
}
@ -249,6 +265,13 @@ type Phrase struct {
// Block represents a scoped/indented block of code.
type Block []Phrase
// FuncOutput represents a function output declaration. It allows for a default
// value.
type FuncOutput struct {
Declaration
valuable
}
// FuncSection represents a function section.
type FuncSection struct {
locatable
@ -257,7 +280,7 @@ type FuncSection struct {
receiver *Declaration
inputs []Declaration
outputs []Declaration
outputs []FuncOutput
root Block
external bool

View File

@ -2,13 +2,13 @@ package parser
import "git.tebibyte.media/arf/arf/lexer"
import "git.tebibyte.media/arf/arf/infoerr"
import "git.tebibyte.media/arf/arf/types"
// 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)
if err != nil { return }
what.location = parser.token.Location()
what.kind = TypeKindBasic
if parser.token.Is(lexer.TokenKindLBrace) {
what.kind = TypeKindPointer
@ -48,11 +48,7 @@ func (parser *ParsingOperation) parseType () (what Type, err error) {
err = parser.skipWhitespace()
if err != nil { return }
err = parser.expect(
lexer.TokenKindName,
lexer.TokenKindUInt,
lexer.TokenKindLParen,
lexer.TokenKindLessThan)
err = parser.expect(lexer.TokenKindName, lexer.TokenKindUInt)
if err != nil { return }
if parser.token.Is(lexer.TokenKindName) {
@ -77,242 +73,8 @@ func (parser *ParsingOperation) parseType () (what Type, err error) {
err = parser.nextToken()
if err != nil { return }
} else if parser.token.Is(lexer.TokenKindLessThan) {
// parse default value
what.defaultValue, err = parser.parseBasicDefaultValue()
if err != nil { return }
} else if parser.token.Is(lexer.TokenKindLParen) {
// parse members and member default values
what.defaultValue,
what.members,
err = parser.parseObjectDefaultValueAndMembers()
if err != nil { return }
}
}
return
}
// parseBasicDefaultValue parses a default value of a non-object type.
func (parser *ParsingOperation) parseBasicDefaultValue () (
value Argument,
err error,
) {
value.location = parser.token.Location()
err = parser.expect(lexer.TokenKindLessThan)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
var attributes []Argument
defer func () {
// if we have multiple values, we need to return the full array
// instead.
if len(attributes) > 1 {
value.kind = ArgumentKindArrayDefaultValues
value.value = ArrayDefaultValues(attributes)
}
} ()
for {
err = parser.skipWhitespace()
if err != nil { return }
if parser.token.Is(lexer.TokenKindGreaterThan) { break }
value, err = parser.parseArgument()
if err != nil { return }
attributes = append(attributes, value)
}
err = parser.nextToken()
if err != nil { return }
return
}
// parseObjectDefaultValueAndMembers parses default values and new members of an
// object type.
func (parser *ParsingOperation) parseObjectDefaultValueAndMembers () (
value Argument,
members []TypeMember,
err error,
) {
value.location = parser.token.Location()
err = parser.expect(lexer.TokenKindLParen)
if err != nil { return }
parser.nextToken()
if err != nil { return }
var attributes ObjectDefaultValues
for {
err = parser.skipWhitespace()
if err != nil { return }
if parser.token.Is(lexer.TokenKindRParen) { break }
err = parser.expect(lexer.TokenKindDot)
if err != nil { return }
parser.nextToken(lexer.TokenKindName, lexer.TokenKindPermission)
if err != nil { return }
if parser.token.Is(lexer.TokenKindName) {
// parsing a defalut value for an inherited member
var memberName string
var memberValue Argument
memberName,
memberValue, err = parser.parseObjectInheritedMember()
if err != nil { return }
if value.kind == ArgumentKindNil {
// create default value map if it doesn't
// already exist
value.kind = ArgumentKindObjectDefaultValues
attributes = make(ObjectDefaultValues)
value.value = attributes
}
// TODO: error on duplicate
if memberValue.kind != ArgumentKindNil {
attributes[memberName] = memberValue
}
} else if parser.token.Is(lexer.TokenKindPermission) {
// parsing a member declaration
var member TypeMember
member, err = parser.parseObjectNewMember()
// TODO: error on duplicate
members = append(members, member)
if err != nil { return }
}
}
err = parser.nextToken()
if err != nil { return }
return
}
// parseObjectDefaultValue parses member default values only, and will throw an
// error when it encounteres a new member definition.
func (parser *ParsingOperation) parseObjectDefaultValue () (
value Argument,
err error,
) {
value.location = parser.token.Location()
err = parser.expect(lexer.TokenKindLParen)
if err != nil { return }
parser.nextToken()
if err != nil { return }
var attributes ObjectDefaultValues
for {
err = parser.skipWhitespace()
if err != nil { return }
if parser.token.Is(lexer.TokenKindRParen) { break }
err = parser.expect(lexer.TokenKindDot)
if err != nil { return }
parser.nextToken(lexer.TokenKindName)
if err != nil { return }
if value.kind == ArgumentKindNil {
value.kind = ArgumentKindObjectDefaultValues
attributes = make(ObjectDefaultValues)
value.value = attributes
}
var memberName string
var memberValue Argument
memberName,
memberValue, err = parser.parseObjectInheritedMember()
attributes[memberName] = memberValue
}
err = parser.nextToken()
if err != nil { return }
return
}
// .name:<value>
// parseObjectInheritedMember parses a new default value for an inherited
// member.
func (parser *ParsingOperation) parseObjectInheritedMember () (
name string,
value Argument,
err error,
) {
// get the name of the inherited member
err = parser.expect(lexer.TokenKindName)
value.location = parser.token.Location()
if err != nil { return }
name = parser.token.Value().(string)
// we require a default value to be present
err = parser.nextToken(lexer.TokenKindColon)
if err != nil { return }
err = parser.nextToken(lexer.TokenKindLParen, lexer.TokenKindLessThan)
if err != nil { return }
if parser.token.Is(lexer.TokenKindLessThan) {
// parse default value
value, err = parser.parseBasicDefaultValue()
if err != nil { return }
} else if parser.token.Is(lexer.TokenKindLParen) {
// parse member default values
value, err = parser.parseObjectDefaultValue()
if err != nil { return }
}
return
}
// .ro name:Type:qualifier:<value>
// parseObjectNewMember parses an object member declaration, and its
// default value if it exists.
func (parser *ParsingOperation) parseObjectNewMember () (
member TypeMember,
err error,
) {
// get member permission
err = parser.expect(lexer.TokenKindPermission)
member.location = parser.token.Location()
if err != nil { return }
member.permission = parser.token.Value().(types.Permission)
// get member name
err = parser.nextToken(lexer.TokenKindName)
if err != nil { return }
member.name = parser.token.Value().(string)
// get type
err = parser.nextToken(lexer.TokenKindColon)
if err != nil { return }
err = parser.nextToken(lexer.TokenKindName, lexer.TokenKindLBrace)
if err != nil { return }
member.what, err = parser.parseType()
if err != nil { return }
// get bit width
if parser.token.Is(lexer.TokenKindBinaryAnd) {
err = parser.nextToken(lexer.TokenKindUInt)
if err != nil { return }
member.bitWidth = parser.token.Value().(uint64)
err = parser.nextToken()
if err != nil { return }
}
return
}

View File

@ -3,8 +3,8 @@ package parser
import "git.tebibyte.media/arf/arf/types"
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.
// parseTypeSection parses a type definition. It can inherit from other types,
// and define new members on them.
func (parser *ParsingOperation) parseTypeSection () (
section TypeSection,
err error,
@ -32,10 +32,103 @@ func (parser *ParsingOperation) parseTypeSection () (
section.what, err = parser.parseType()
if err != nil { return }
parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
// see if value exists
if parser.token.Is(lexer.TokenKindNewline) {
parser.nextToken()
// if we have exited the section, return
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 1 { return }
err = parser.nextToken()
if err != nil { return }
}
// if we have not encountered members, get value and return.
if !parser.token.Is(lexer.TokenKindPermission) {
section.argument, err = parser.parseArgument()
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
return
}
parser.previousToken()
for {
// if we have exited the section, return
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 1 { return }
err = parser.nextToken(lexer.TokenKindPermission)
if err != nil { return }
var member TypeSectionMember
member, err = parser.parseTypeSectionMember()
section.members = append(section.members, member)
if err != nil { return }
}
return
}
// parseTypeSectionMember parses a type section member variable.
func (parser *ParsingOperation) parseTypeSectionMember () (
member TypeSectionMember,
err error,
) {
// get permission
err = parser.expect(lexer.TokenKindPermission)
if err != nil { return }
member.permission = parser.token.Value().(types.Permission)
// get name
err = parser.nextToken(lexer.TokenKindName)
if err != nil { return }
member.name = parser.token.Value().(string)
// if there is a type, get it
err = parser.nextToken()
if err != nil { return }
if parser.token.Is(lexer.TokenKindColon) {
err = parser.nextToken(lexer.TokenKindName)
if err != nil { return }
member.what, err = parser.parseType()
if err != nil { return }
}
// see if value exists
if parser.token.Is(lexer.TokenKindNewline) {
parser.nextToken()
// if we have exited the member, return
if !parser.token.Is(lexer.TokenKindIndent) { return }
if parser.token.Value().(int) != 2 { return }
err = parser.nextToken()
if err != nil { return }
}
// if default value exists, get it
if !parser.token.Is(lexer.TokenKindBinaryAnd) {
member.argument, err = parser.parseArgument()
}
// if there is a bit width specifier, get it
if parser.token.Is(lexer.TokenKindBinaryAnd) {
err = parser.nextToken(lexer.TokenKindUInt)
if err != nil { return }
member.bitWidth = parser.token.Value().(uint64)
err = parser.nextToken()
if err != nil { return }
}
err = parser.expect(lexer.TokenKindNewline)
if err != nil { return }
err = parser.nextToken()
if err != nil { return }
return
}

View File

@ -6,55 +6,34 @@ func TestType (test *testing.T) {
checkTree ("../tests/parser/type", false,
`:arf
---
type ro aBasic:Obj:
(
.ro that:Int
.ro this:Int
)
type ro bBitFields:Obj:
(
.ro that:Int & 1
.ro this:Int:<298> & 24
)
type ro cInit:Obj:
(
.ro that:String:<"hello world">
.ro this:Int:<23>
)
type ro dInitInherit:aBasic:
(
.that:<9384>
.this:<389>
)
type ro eInitAndDefine:aBasic:
(
.ro these:aBasic:
(
.ro born:Int:<4>
.ro in:Int
.ro the:Int:3:
<
9348
92384
92834
>
):
(
.this:<98>
)
):
(
.that:<9384>
.this:<389>
)
type ro aBasic:Obj
ro that:Int
ro this:Int
type ro bBitFields:Obj
ro that:Int & 1
ro this:Int 298 & 24
type ro cInit:Obj
ro that:String "hello world"
ro this:Int 23
type ro dInitInherit:aBasic
ro that 9384
ro this 389
type ro eInitAndDefine:aBasic
ro this 389
ro that 9384
ro born:Int 4
ro in:Int
ro the:Int:3 (9348 92384 92834)
ro walls:String "live in the walls, die in the walls."
type ro fBasic:Int
type ro gBasicInit:Int:<6>
type ro gBasicInit:Int
6
type ro hIntArray:{Int ..}
type ro iIntArrayInit:Int:3:
<
type ro iIntArrayInit:Int:3
(
3298
923
92
>
)
`, test)
}

View File

@ -1,9 +1,9 @@
:arf
---
data ro aInteger:Int:<3202>
data ro aInteger:Int 3202
data ro bMutInteger:Int:mut:<3202>
data ro bMutInteger:Int:mut 3202
data ro cIntegerPointer:{Int}
@ -13,33 +13,30 @@ data ro eIntegerArray16:Int:16
data ro fIntegerArrayVariable:{Int ..}
data ro gIntegerArrayInitialized:Int:16:<
3948 293 293049 948 912
340 0 2304 0 4785 92
>
data ro gIntegerArrayInitialized:Int:16
(3948 293 293049 948 912
340 0 2304 0 4785 92)
data rw hIntegerPointerInit:{Int}:<[& integer]>
data rw hIntegerPointerInit:{Int} [& integer]
data rw iMutIntegerPointerInit:{Int}:mut:<[& integer]>
data rw iMutIntegerPointerInit:{Int}:mut
[& integer]
data ro jObject:Obj:(
.this:<324>
.that:<324>)
data ro jObject:Obj
(324
438)
data ro kNestedObject:Obj:(
.this:(
.bird0:<324>
.bird1:<"hello world">)
.ro newMember:Int:<9023>
.that:(
.bird2:<123.8439>
.bird3:<9328.21348239>))
# TODO: at some point, have this syntax for object literals. terminate members
# with newlines.
# data ro jObject:Bird (
# .this 324
# .that 438)
data ro lMutIntegerArray16:Int:16:mut
data ro mExternalData:Int:8
external
data ro nIntegerArrayInitialized:Int:16:mut:
<3948 293 293049 948 912
340 0 2304 0 4785 92>
data ro nIntegerArrayInitialized:Int:16:mut
(3948 293 293049 948 912
340 0 2304 0 4785 92)

View File

@ -11,26 +11,26 @@ enum ro Weekday:Int
- saturday
enum ro NamedColor:U32
- red: <0xFF0000>
- green: <0x00FF00>
- blue: <0x0000FF>
- red 0xFF0000
- green 0x00FF00
- blue 0x0000FF
enum ro AffrontToGod:Int:4
- bird0:
<28394 9328
398 9>
- bird1:
<23 932832
- bird0
(28394 9328
398 9)
- bird1
(23 932832
398
2349>
- bird2:
<1
2349)
- bird2
(1
2
3
4>
4)
enum ro ThisIsTerrible:Obj:(.rw x:Int .rw y:Int)
- up: (.x:< 0> .y:<-1>)
- down: (.x:< 0> .y:< 1>)
- left: (.x:<-1> .y:< 0>)
- right: (.x:< 1> .y:< 0>)
enum ro ThisIsTerrible:Vector
- up ( 0 -1)
- down ( 0 1)
- left (-1 0)
- right ( 1 0)

View File

@ -1,7 +1,7 @@
:arf
---
face ro ReadWriter:Face
face ro aReadWriter:Face
write
> data:{Byte ..}
< wrote:Int
@ -11,5 +11,10 @@ face ro ReadWriter:Face
< read:Int
< err:Error
face ro Destroyer:Face
face ro bDestroyer:Face
destroy
face ro cFuncInterface:Func
> something:Int
< someOutput:Int
< otherOutput:String

View File

@ -2,14 +2,14 @@
---
func ro aBasicExternal
> someInput:Int:mut
< someOutput:Int:<4>
< someOutput:Int 4
---
external
func ro bMethod
@ bird:{Bird}
> someInput:Int:mut
< someOutput:Int:<4>
< someOutput:Int 4
---
external
@ -122,14 +122,13 @@ func ro gControlFlow
else
otherThing
func ro hSetPhrase
func ro hDataInit
---
let x:Int:<3>
= x:Int 3
# loc is a reference, similar to * in C
let y:{Int}:<[loc x]>
let z:Int:8:
<398 9 2309 983 -2387
478 555 123>
let bird:Bird:(
.that:(.whenYou:<99999>)
.this:<324>)
= y:{Int} [loc x]
= z:Int:8 (398 9 2309 983 -2387
478 555 123)
= bird:Bird (
(99999)
324)

View File

@ -6,37 +6,33 @@ data ro aExternalData:Int
data ro bSingleValue:Int 342
data ro cNestedObject:Obj
-- this
-- bird0 324
-- bird1 "hello world"
-- that
-- bird2 123.8439
-- bird3 9328.21348239
data ro cNestedObject:Obj (
(324 "hello world")
(123.8439 9328.21348239)
)
data ro dUninitialized:Int:16:mut
data ro eIntegerArrayInitialized:Int:16:mut
3948 293 293049 948 912
340 0 2304 0 4785 92
(3948 293 293049 948 912
340 0 2304 0 4785 92)
func ro fComplexFunction
---
= x:Int 3
= y:{Int} [loc x]
= z:Int:8
= y:{Int
} [loc x
]
= z:Int:8 (
398 9 2309 983 -2387
478 555 123
= bird:Bird
-- that
-- whenYou 99999
-- this 324
478 555 123)
= bird:Bird ((99999) 324)
func ro gExternalFunction
> x:Int
< arr:Int 5
34908
(34908
39 3498
38 219
38 219)
---
external

View File

@ -1,35 +1,36 @@
:arf
---
type ro aBasic:Obj:(
.ro that:Int
.ro this:Int)
type ro aBasic:Obj
ro that:Int
ro this:Int
type ro bBitFields:Obj:(
.ro that:Int & 1
.ro this:Int:<298> & 24)
type ro bBitFields:Obj
ro that:Int & 1
ro this:Int 298 & 24
type ro cInit:Obj:(
.ro that:String:<"hello world">
.ro this:Int:<23>)
type ro cInit:Obj
ro that:String "hello world"
ro this:Int 23
type ro dInitInherit:aBasic:(
.that:<9384>
.this:<389>)
# the semantic analyzer should let these sections restrict the permissions of
# inherited members, but it should not let the sections lessen the permissions.
type ro dInitInherit:aBasic
ro that 9384
ro this 389
type ro eInitAndDefine:aBasic:(
.this:<389>
.ro these:aBasic:(
.ro born:Int:<4>
.ro in:Int
.ro the:Int:3:<9348 92384 92834>
.this:<98>)
.that:<9384>)
type ro eInitAndDefine:aBasic
ro this 389
ro that 9384
ro born:Int 4
ro in:Int
ro the:Int:3 (9348 92384 92834)
ro walls:String "live in the walls, die in the walls."
type ro fBasic:Int
type ro gBasicInit:Int:<6>
type ro gBasicInit:Int 6
type ro hIntArray:{Int ..}
type ro iIntArrayInit:Int:3:
<3298 923 92>
type ro iIntArrayInit:Int:3
(3298 923 92)