1- import { ExpressionName } from "../../ast/types/blocks-and-statements" ;
1+ import {
2+ ExpressionName ,
3+ VariableInitializer ,
4+ } from "../../ast/types/blocks-and-statements" ;
25import { Frame } from "./environment" ;
36import { Method } from "../types/methods" ;
47import { Node } from "../../ast/types/ast" ;
5- import { String } from "../types/nonPrimitives" ;
8+ import { Integer , String } from "../types/nonPrimitives" ;
69import { Type } from "../types/type" ;
710import {
11+ ArrayRequiredError ,
812 BadOperandTypesError ,
913 IncompatibleTypesError ,
1014 VariableAlreadyDefinedError ,
@@ -25,6 +29,7 @@ import {
2529 getFloatType ,
2630 getNumberType ,
2731} from "../types/primitives" ;
32+ import { Array as ArrayType } from "../types/arrays" ;
2833
2934export type Result = {
3035 currentType : Type | null ;
@@ -43,6 +48,28 @@ export const check = (
4348 frame : Frame = Frame . globalFrame ( )
4449) : Result => {
4550 switch ( node . kind ) {
51+ case "ArrayAccess" : {
52+ const primaryCheck = check ( node . primary , frame ) ;
53+ if ( primaryCheck . errors . length > 0 )
54+ return newResult ( null , primaryCheck . errors ) ;
55+ if ( ! ( primaryCheck . currentType instanceof ArrayType ) )
56+ return newResult ( null , [ new ArrayRequiredError ( ) ] ) ;
57+ const expressionCheck = check ( node . expression , frame ) ;
58+ if ( expressionCheck . errors . length > 0 )
59+ return newResult ( null , expressionCheck . errors ) ;
60+ if ( ! expressionCheck . currentType )
61+ throw new Error ( "Expression check should return a type." ) ;
62+ const integerType = new Integer ( ) ;
63+ const intType = new Int ( ) ;
64+ if (
65+ ! (
66+ integerType . equals ( expressionCheck . currentType ) ||
67+ intType . equals ( expressionCheck . currentType )
68+ )
69+ )
70+ return newResult ( null , [ new IncompatibleTypesError ( ) ] ) ;
71+ return newResult ( primaryCheck . currentType . getContentType ( ) ) ;
72+ }
4673 case "Assignment" : {
4774 const left = node . left as ExpressionName ;
4875 const right = node . right ;
@@ -253,31 +280,51 @@ export const check = (
253280 case "LocalVariableDeclarationStatement" : {
254281 if ( ! node . variableDeclaratorList )
255282 throw new Error ( "Variable declarator list is undefined." ) ;
283+ const errors : Error [ ] = [ ] ;
256284 const results = node . variableDeclaratorList . map ( ( variableDeclarator ) => {
257285 const declaredType = frame . getType ( node . localVariableType ) ;
258286 if ( declaredType instanceof Error )
259287 return newResult ( null , [ declaredType ] ) ;
260288 const { variableInitializer } = variableDeclarator ;
261- if ( ! variableInitializer )
262- throw new Error ( "Variable initializer is undefined." ) ;
263- if ( Array . isArray ( variableInitializer ) ) {
264- // Is array initializer
265- } else {
266- // Is not array initializer
267- const { currentType, errors } = check ( variableInitializer , frame ) ;
268- if ( errors . length > 0 ) return { currentType : null , errors } ;
269- if ( currentType == null )
270- throw new Error (
271- "Variable initializer in local variable declaration statement should return a type."
272- ) ;
273- if ( ! declaredType . canBeAssigned ( currentType ) )
274- return newResult ( null , [ new IncompatibleTypesError ( ) ] ) ;
289+ if ( variableInitializer ) {
290+ const checkInitialization = (
291+ declaredType : Type | ArrayType ,
292+ variableInitializer : VariableInitializer
293+ ) : void => {
294+ if ( errors . length > 0 ) return ;
295+ if ( ! Array . isArray ( variableInitializer ) ) {
296+ if ( declaredType instanceof ArrayType ) {
297+ errors . push ( new IncompatibleTypesError ( ) ) ;
298+ return ;
299+ }
300+ const checkResult = check ( variableInitializer , frame ) ;
301+ if ( checkResult . errors . length > 0 ) {
302+ errors . push ( ...checkResult . errors ) ;
303+ return ;
304+ }
305+ if ( checkResult . currentType == null )
306+ throw new Error ( "Variable initializer should return a type." ) ;
307+ if ( ! declaredType . canBeAssigned ( checkResult . currentType ) )
308+ errors . push ( new IncompatibleTypesError ( ) ) ;
309+ return ;
310+ }
311+ if ( ! ( declaredType instanceof ArrayType ) ) {
312+ errors . push ( new IncompatibleTypesError ( ) ) ;
313+ return ;
314+ }
315+ const arrayContentType = declaredType . getContentType ( ) ;
316+ variableInitializer . forEach ( ( variableInitializer ) => {
317+ checkInitialization ( arrayContentType , variableInitializer ) ;
318+ } ) ;
319+ } ;
320+ checkInitialization ( declaredType , variableInitializer ) ;
275321 }
322+ if ( errors . length > 0 ) return newResult ( null , errors ) ;
276323 const error = frame . setVariable (
277324 variableDeclarator . variableDeclaratorId ,
278325 declaredType
279326 ) ;
280- if ( error ) return newResult ( null , [ error ] ) ;
327+ if ( error ) return newResult ( null , [ ... errors , error ] ) ;
281328 return OK_RESULT ;
282329 } ) ;
283330 return results . reduce ( ( previousResult , currentResult ) => {
@@ -472,6 +519,7 @@ export const check = (
472519 return OK_RESULT ;
473520 }
474521 default :
522+ console . log ( node ) ;
475523 throw new Error (
476524 `Check is not implemented for this type of node ${ node . kind } .`
477525 ) ;
0 commit comments