Skip to content

Commit

Permalink
支持变量定义 (#5)
Browse files Browse the repository at this point in the history
* 补全零值

* 支持变量定义
  • Loading branch information
kkkunny authored Oct 26, 2023
1 parent 2c8392b commit 3d07f6c
Show file tree
Hide file tree
Showing 17 changed files with 117 additions and 24 deletions.
4 changes: 2 additions & 2 deletions analyse/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ func (self *Analyser) analyseExtract(expect Type, node *ast.Extract) *Extract {
}

func (self *Analyser) analyseStruct(node *ast.Struct) *Struct {
st := self.analyseIdentType(node.Type).(*StructDef)
st := self.analyseIdentType(node.Type).(*StructType)
fieldNames := hashset.NewHashSet[string]()
for iter := st.Fields.Keys().Iterator(); iter.Next(); {
fieldNames.Push(iter.Value())
Expand Down Expand Up @@ -373,7 +373,7 @@ func (self *Analyser) analyseStruct(node *ast.Struct) *Struct {
func (self *Analyser) analyseField(node *ast.Field) *Field {
from := self.analyseExpr(nil, node.From)
fieldName := node.Index.Source()
st, ok := from.GetType().(*StructDef)
st, ok := from.GetType().(*StructType)
if !ok {
// TODO: 编译时异常:不能获取类型A的字段
panic("unreachable")
Expand Down
8 changes: 4 additions & 4 deletions analyse/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ type _Scope interface {
// 包作用域
type _PkgScope struct {
values hashmap.HashMap[string, Ident]
structs hashmap.HashMap[string, *StructDef]
structs hashmap.HashMap[string, *StructType]
}

func _NewPkgScope() *_PkgScope {
return &_PkgScope{
values: hashmap.NewHashMap[string, Ident](),
structs: hashmap.NewHashMap[string, *StructDef](),
structs: hashmap.NewHashMap[string, *StructType](),
}
}

Expand All @@ -37,15 +37,15 @@ func (self *_PkgScope) GetValue(name string) (Ident, bool) {
return self.values.Get(name), self.values.ContainKey(name)
}

func (self *_PkgScope) SetStruct(st *StructDef) bool {
func (self *_PkgScope) SetStruct(st *StructType) bool {
if self.structs.ContainKey(st.Name) {
return false
}
self.structs.Set(st.Name, st)
return true
}

func (self *_PkgScope) GetStruct(name string) (*StructDef, bool) {
func (self *_PkgScope) GetStruct(name string) (*StructType, bool) {
return self.structs.Get(name), self.structs.ContainKey(name)
}

Expand Down
14 changes: 14 additions & 0 deletions analyse/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ func (self *Analyser) analyseStmt(node ast.Stmt) (Stmt, bool) {
switch stmtNode := node.(type) {
case *ast.Return:
return self.analyseReturn(stmtNode), true
case *ast.Variable:
return self.analyseVariable(stmtNode), false
case ast.Expr:
return self.analyseExpr(nil, stmtNode), false
default:
Expand Down Expand Up @@ -48,3 +50,15 @@ func (self *Analyser) analyseReturn(node *ast.Return) *Return {
return &Return{Value: util.None[Expr]()}
}
}

func (self *Analyser) analyseVariable(node *ast.Variable) *Variable {
v := &Variable{Name: node.Name.Source()}
if !self.localScope.SetValue(v.Name, v) {
// TODO: 编译时异常:变量名冲突
panic("unreachable")
}

v.Type = self.analyseType(node.Type)
v.Value = self.expectExpr(v.Type, node.Value)
return v
}
16 changes: 16 additions & 0 deletions ast/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/kkkunny/stl/container/linkedlist"

"github.com/kkkunny/Sim/reader"
"github.com/kkkunny/Sim/token"
"github.com/kkkunny/Sim/util"
)

Expand All @@ -26,6 +27,7 @@ func (self *Block) Position() reader.Position {

func (self *Block) stmt() {}

// Return 函数返回
type Return struct {
Begin reader.Position
Value util.Option[Expr]
Expand All @@ -40,3 +42,17 @@ func (self *Return) Position() reader.Position {
}

func (self *Return) stmt() {}

// Variable 变量定义
type Variable struct {
Begin reader.Position
Name token.Token
Type Type
Value Expr
}

func (self *Variable) Position() reader.Position {
return reader.MixPosition(self.Begin, self.Value.Position())
}

func (self *Variable) stmt() {}
8 changes: 6 additions & 2 deletions codegen/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func (self *CodeGenerator) codegenIdent(node mean.Ident) llvm.Value {
case *mean.FuncDef:
f := self.module.GetFunction(identNode.Name)
return f
case *mean.Param:
case *mean.Param, *mean.Variable:
p := self.values[identNode]
t := self.codegenType(node.GetType())
return self.builder.CreateLoad("", t, p)
Expand Down Expand Up @@ -325,6 +325,10 @@ func (self *CodeGenerator) codegenZero(node *mean.Zero) llvm.Value {
return self.ctx.ConstFloat(t.(llvm.FloatType), 0)
case *mean.BoolType:
return self.ctx.ConstInteger(t.(llvm.IntegerType), 0)
case *mean.ArrayType:
return self.ctx.ConstAggregateZero(t.(llvm.ArrayType))
case *mean.StructType:
return self.ctx.ConstAggregateZero(t.(llvm.StructType))
default:
panic("unreachable")
}
Expand All @@ -334,7 +338,7 @@ func (self *CodeGenerator) codegenStruct(node *mean.Struct) llvm.Value {
fields := lo.Map(node.Fields, func(item mean.Expr, index int) llvm.Value {
return self.codegenExpr(item)
})
t := self.codegenStructType(node.GetType().(*mean.StructDef))
t := self.codegenStructType(node.GetType().(*mean.StructType))
ptr := self.builder.CreateAlloca("", t)
for i, field := range fields {
ep := self.builder.CreateStructGEP("", t, ptr, uint(i))
Expand Down
10 changes: 10 additions & 0 deletions codegen/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ func (self *CodeGenerator) codegenStmt(node mean.Stmt) {
switch stmtNode := node.(type) {
case *mean.Return:
self.codegenReturn(stmtNode)
case *mean.Variable:
self.codegenVariable(stmtNode)
case mean.Expr:
self.codegenExpr(stmtNode)
default:
Expand Down Expand Up @@ -39,3 +41,11 @@ func (self *CodeGenerator) codegenReturn(node *mean.Return) {
self.builder.CreateRet(nil)
}
}

func (self *CodeGenerator) codegenVariable(node *mean.Variable) {
t := self.codegenType(node.Type)
value := self.codegenExpr(node.Value)
ptr := self.builder.CreateAlloca("", t)
self.builder.CreateStore(value, ptr)
self.values[node] = ptr
}
4 changes: 2 additions & 2 deletions codegen/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (self *CodeGenerator) codegenType(node mean.Type) llvm.Type {
return self.codegenArrayType(typeNode)
case *mean.TupleType:
return self.codegenTupleType(typeNode)
case *mean.StructDef:
case *mean.StructType:
return self.codegenStructType(typeNode)
default:
panic("unreachable")
Expand Down Expand Up @@ -77,7 +77,7 @@ func (self *CodeGenerator) codegenTupleType(node *mean.TupleType) llvm.StructTyp
return self.ctx.StructType(false, elems...)
}

func (self *CodeGenerator) codegenStructType(node *mean.StructDef) llvm.StructType {
func (self *CodeGenerator) codegenStructType(node *mean.StructType) llvm.StructType {
fields := make([]llvm.Type, node.Fields.Length())
var i int
for iter := node.Fields.Iterator(); iter.Next(); i++ {
Expand Down
11 changes: 2 additions & 9 deletions example/main.sim
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
struct T{
data: u8
}

func get()T{
return T{data: 1}
}

func main()u8{
return get().data - 1
let i: u8 = 1;
return i
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.21.3
require github.com/kkkunny/stl v0.0.0-20231022115244-2d9f235921a3

require (
github.com/kkkunny/go-llvm v0.0.0-20231022112819-c995932e65e0
github.com/kkkunny/go-llvm v0.0.0-20231022134249-a7ebd2dcb283
github.com/samber/lo v1.38.1
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/kkkunny/go-llvm v0.0.0-20231022091327-288268740f4d h1:GTKwPcr9hrQBGUw
github.com/kkkunny/go-llvm v0.0.0-20231022091327-288268740f4d/go.mod h1:3vOsdDMD0flAC4YHxfqUZ2juZ40oCI/5HBIVPKGLT34=
github.com/kkkunny/go-llvm v0.0.0-20231022112819-c995932e65e0 h1:TrL7WoxBUXfMdoNwFOWKOGWo9oBZTAkCmnczcEy5/YA=
github.com/kkkunny/go-llvm v0.0.0-20231022112819-c995932e65e0/go.mod h1:3vOsdDMD0flAC4YHxfqUZ2juZ40oCI/5HBIVPKGLT34=
github.com/kkkunny/go-llvm v0.0.0-20231022134249-a7ebd2dcb283 h1:BwHJQXiNrXXMiXDnFxsVTRXOsatEqtVOKwAyoVc06AA=
github.com/kkkunny/go-llvm v0.0.0-20231022134249-a7ebd2dcb283/go.mod h1:3vOsdDMD0flAC4YHxfqUZ2juZ40oCI/5HBIVPKGLT34=
github.com/kkkunny/stl v0.0.0-20231014052322-46f1c45686f0 h1:VAtB9hn2SIdUjV9o+1ieqoaMQ95cuwgnzdbJGyrLBn4=
github.com/kkkunny/stl v0.0.0-20231014052322-46f1c45686f0/go.mod h1:4TbqW9zjHIpp/0Auz1/nyec9WsiMN878ifaEPwVSdkE=
github.com/kkkunny/stl v0.0.0-20231022115244-2d9f235921a3 h1:okBRIiEPszBnpp5S+QAIFrXKh1uzoxE6cpCI26vuFlU=
Expand Down
2 changes: 2 additions & 0 deletions lex/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ func (self *Lexer) Scan() Token {
switch ch {
case 0:
kind = EOF
case '=':
kind = ASS
case '&':
kind = AND
case '|':
Expand Down
4 changes: 2 additions & 2 deletions mean/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ func (*Param) ident() {}

// Struct 结构体
type Struct struct {
Type *StructDef
Type *StructType
Fields []Expr
}

Expand Down Expand Up @@ -439,5 +439,5 @@ type Field struct {
func (self *Field) stmt() {}

func (self *Field) GetType() Type {
return self.From.GetType().(*StructDef).Fields.Values().Get(self.Index)
return self.From.GetType().(*StructType).Fields.Values().Get(self.Index)
}
20 changes: 18 additions & 2 deletions mean/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,26 @@ type Block struct {
Stmts linkedlist.LinkedList[Stmt]
}

func (self *Block) stmt() {}
func (*Block) stmt() {}

// Return 函数返回
type Return struct {
Value util.Option[Expr]
}

func (self *Return) stmt() {}
func (*Return) stmt() {}

// Variable 变量定义
type Variable struct {
Type Type
Name string
Value Expr
}

func (*Variable) stmt() {}

func (self *Variable) GetType() Type {
return self.Type
}

func (*Variable) ident() {}
2 changes: 2 additions & 0 deletions mean/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,5 @@ func (self *TupleType) Equal(dst Type) bool {
}
return true
}

type StructType = StructDef
17 changes: 17 additions & 0 deletions parse/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ func (self *Parser) parseStmt() Stmt {
switch self.nextTok.Kind {
case token.RETURN:
return self.parseReturn()
case token.LET:
return self.parseVariable()
default:
return self.mustExpr(self.parseOptionExpr(true))
}
Expand Down Expand Up @@ -47,3 +49,18 @@ func (self *Parser) parseReturn() *Return {
Value: value,
}
}

func (self *Parser) parseVariable() *Variable {
begin := self.expectNextIs(token.LET).Position
name := self.expectNextIs(token.IDENT)
self.expectNextIs(token.COL)
typ := self.parseType()
self.expectNextIs(token.ASS)
value := self.mustExpr(self.parseOptionExpr(true))
return &Variable{
Begin: begin,
Name: name,
Type: typ,
Value: value,
}
}
12 changes: 12 additions & 0 deletions test/variable_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package test

import "testing"

func TestVariable(t *testing.T) {
assertRetEqZero(t, `
func main()u8{
let i: u8 = 1;
return i - 1
}
`)
}
5 changes: 5 additions & 0 deletions token/kind.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const (
INTEGER
FLOAT

ASS

AND
OR
XOR
Expand Down Expand Up @@ -45,6 +47,7 @@ const (
FALSE
AS
STRUCT
LET
_KeywordEnd
)

Expand All @@ -54,6 +57,7 @@ var kindNames = [...]string{
IDENT: "ident",
INTEGER: "integer",
FLOAT: "float",
ASS: "ass",
AND: "and",
OR: "or",
XOR: "xor",
Expand Down Expand Up @@ -82,6 +86,7 @@ var kindNames = [...]string{
FALSE: "false",
AS: "as",
STRUCT: "struct",
LET: "let",
}

// Lookup 区分标识符和关键字
Expand Down

0 comments on commit 3d07f6c

Please sign in to comment.