expr5.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package compiler
  2. import (
  3. "regexp"
  4. "strings"
  5. "strconv"
  6. "unicode/utf8"
  7. "kumachan/standalone/util"
  8. "kumachan/lang/source"
  9. "kumachan/lang/typsys"
  10. "kumachan/lang/textual/ast"
  11. "kumachan/interpreter/program"
  12. )
  13. func checkInt(I ast.Int, cc *exprCheckContext) (*program.Expr, *source.Error) {
  14. if typsys.Equal(cc.expected, program.T_Float()) {
  15. return cc.forwardTo(ast.WrapTermAsExpr(ast.VariousTerm {
  16. Node: I.Node,
  17. Term: ast.Float {
  18. Node: I.Node,
  19. Value: I.Value,
  20. },
  21. }))
  22. }
  23. var loc = I.Location
  24. var value, ok = util.WellBehavedParseInteger(source.CodeToChars(I.Value))
  25. if !(ok) {
  26. panic("something went wrong")
  27. }
  28. var int_t = typsys.CertainType { Type: program.T_Int() }
  29. return cc.assign(int_t, loc,
  30. program.IntLiteral {
  31. Value: value,
  32. })
  33. }
  34. func checkFloat(F ast.Float, cc *exprCheckContext) (*program.Expr, *source.Error) {
  35. var loc = F.Location
  36. var value, ok = util.ParseDouble(source.CodeToChars(F.Value))
  37. if !(ok) {
  38. return cc.error(loc, E_InvalidFloat {})
  39. }
  40. if !(util.IsNormalFloat(value)) {
  41. panic("something went wrong")
  42. }
  43. var float_t = typsys.CertainType { Type: program.T_Float() }
  44. return cc.assign(float_t, loc,
  45. program.FloatLiteral {
  46. Value: value,
  47. })
  48. }
  49. func checkChar(C ast.Char, cc *exprCheckContext) (*program.Expr, *source.Error) {
  50. var loc = C.Location
  51. var value, err = parseCharLiteral(C.Value)
  52. if err != nil { return cc.error(loc, err) }
  53. var char_t = typsys.CertainType { Type: program.T_Char() }
  54. return cc.assign(char_t, loc,
  55. program.CharLiteral {
  56. Value: value,
  57. })
  58. }
  59. func checkBytes(B ast.Bytes, cc *exprCheckContext) (*program.Expr, *source.Error) {
  60. var loc = B.Location
  61. var value = make([] byte, len(B.Bytes))
  62. for i, b := range B.Bytes {
  63. var x = hexDigitCharToByte(b.Value[2])
  64. var y = hexDigitCharToByte(b.Value[3])
  65. value[i] = ((x << 4) | y)
  66. }
  67. var bytes_t = typsys.CertainType { Type: program.T_Bytes() }
  68. return cc.assign(bytes_t, loc,
  69. program.BytesLiteral {
  70. Value: value,
  71. })
  72. }
  73. func hexDigitCharToByte(d uint16) byte {
  74. if d >= 'a' {
  75. return byte(10 + (d - 'a'))
  76. } else if d >= 'A' {
  77. return byte(10 + (d - 'A'))
  78. } else {
  79. return byte(d - '0')
  80. }
  81. }
  82. func checkString(S ast.String, cc *exprCheckContext) (*program.Expr, *source.Error) {
  83. var buf strings.Builder
  84. var first = S.First
  85. var s, err = normalizeText(first.Value)
  86. if err != nil { return cc.error(first.Location, err) }
  87. buf.WriteString(s)
  88. for _, part := range S.Parts {
  89. switch P := part.Content.StringPartContent.(type) {
  90. case ast.Text:
  91. var s, err = normalizeText(P.Value)
  92. if err != nil { return cc.error(P.Location, err) }
  93. buf.WriteString(s)
  94. case ast.Char:
  95. var r, err = parseCharLiteral(P.Value)
  96. if err != nil { return cc.error(P.Location, err) }
  97. buf.WriteRune(r)
  98. default:
  99. panic("impossible branch")
  100. }
  101. }
  102. var value = buf.String()
  103. var loc = S.Location
  104. if typsys.Equal(cc.expected, program.T_RegExp()) {
  105. var value, err = compileRegexpLiteral(value)
  106. if err != nil { return cc.error(loc, err) }
  107. var regexp_t = typsys.CertainType { Type: program.T_RegExp() }
  108. return cc.assign(regexp_t, loc,
  109. program.RegexpLiteral {
  110. Value: value,
  111. })
  112. }
  113. var string_t = typsys.CertainType { Type: program.T_String() }
  114. return cc.assign(string_t, loc,
  115. program.StringLiteral {
  116. Value: value,
  117. })
  118. }
  119. func normalizeText(code source.Code) (string, source.ErrorContent) {
  120. var L = len(code)
  121. if code[0] == '\'' && code[L-1] == '\'' {
  122. return source.CodeToString(code[1:(L-1)]), nil
  123. } else if code[0] == '"' && code[L-1] == '"' {
  124. var u, err = strconv.Unquote(source.CodeToString(code))
  125. if err != nil {
  126. return "", E_InvalidText {}
  127. }
  128. return u, nil
  129. } else {
  130. panic("impossible branch")
  131. }
  132. }
  133. func parseCharLiteral(code source.Code) (rune, source.ErrorContent) {
  134. var value, ok = util.ParseRune(source.CodeToChars(code))
  135. if ok {
  136. return value, nil
  137. } else {
  138. return utf8.RuneError, E_InvalidChar {}
  139. }
  140. }
  141. func compileRegexpLiteral(str string) (*regexp.Regexp, source.ErrorContent) {
  142. var value, err = regexp.Compile(str)
  143. if err == nil {
  144. return value, nil
  145. } else {
  146. return nil, E_InvalidRegexp {
  147. Detail: err.Error(),
  148. }
  149. }
  150. }