@@ -6,7 +6,7 @@ import child_process from "node:child_process";
66
77const { execFileSync } = child_process ;
88
9- function indent ( str : string , n : number ) : string {
9+ function indent ( str : string , n : number = 1 ) : string {
1010 return str
1111 . split ( / \r ? \n / )
1212 . map ( ( line ) => " " . repeat ( n ) + line )
@@ -343,7 +343,7 @@ class ArrayType extends Type {
343343 zero ( code : string [ ] ) : string {
344344 if ( ! this . dynamic ) return "{0}" ;
345345 const r = this . hi . context ( ) . R ( ) ;
346- code . push ( `void *${ r } AUTOFREE = malloc(sizeof(${ this . type . c ( ) } ) * (${ this . sz ( ) } ));` ) ;
346+ code . push ( `void *${ r } AUTOFREE_ARRAY = malloc(sizeof(${ this . type . c ( ) } ) * (${ this . sz ( ) } ));` ) ;
347347 return `{ .data = ${ r } }` ;
348348 }
349349 typedef = ( alias : string ) => `typedef ${ this . c ( ) } ${ alias } ` ;
@@ -714,6 +714,7 @@ class SET extends Statement {
714714 `type mismatch in SET: ${ type . constructor . name } !== ${ this . expression . type . constructor . name } at ${ this . token } `
715715 ) ;
716716 }
717+
717718 const value = this . expression . v ( code ) ;
718719 code . push ( `${ reference } = ${ value } ;` ) ;
719720 }
@@ -858,8 +859,11 @@ class INPUT extends Statement {
858859 const { type, reference } = expand_variable_reference ( variable , variable_reference , code ) ;
859860
860861 if ( type instanceof StringType ) {
861- code . push ( `scanf("%4095s", ${ reference } .data);` ) ;
862- code . push ( `${ reference } .sz = strlen(${ reference } .data);` ) ;
862+ code . push ( `{` ) ;
863+ code . push ( indent ( `char buf[4096];` , 1 ) ) ;
864+ code . push ( indent ( `scanf("%4095s", buf);` , 1 ) ) ;
865+ code . push ( indent ( `${ reference } = make_string(buf, strlen(buf));` , 1 ) ) ;
866+ code . push ( `}` ) ;
863867 } else if ( type instanceof IntegerType ) code . push ( `scanf("%d", &${ reference } );` ) ;
864868 else if ( type instanceof RealType ) code . push ( `scanf("%lf", &${ reference } );` ) ;
865869 else throw new GenerateError ( `unsupported variable '${ variable } ' type in INPUT at ${ variable . token } ` ) ;
@@ -1058,10 +1062,18 @@ function string_compare(left: Expression, right: Expression, operation: string,
10581062 if ( operation !== "==" && operation !== "!=" ) return null ;
10591063
10601064 function is_string_type ( e : Expression ) : [ boolean , string | null ] {
1061- if ( ! ( e instanceof VariableReference ) ) return [ false , null ] ;
1062- const variable = find_existing_variable ( e ) ;
1063- const { type, reference } = expand_variable_reference ( variable , e , [ ] ) ;
1064- return [ type instanceof StringType , reference ] ;
1065+ if ( e instanceof VariableReference ) {
1066+ const variable = find_existing_variable ( e ) ;
1067+ const { type, reference } = expand_variable_reference ( variable , e , [ ] ) ;
1068+ return [ type instanceof StringType , reference ] ;
1069+ }
1070+ if ( e . type instanceof StringType ) return [ true , e . v ( code ) ] ;
1071+ if ( e instanceof FunctionCall ) {
1072+ const func = e . context ( ) . functions [ e . name ] ;
1073+ if ( ! func ) throw new GenerateError ( `unknown function '${ e . name } ' at ${ e . token } ` ) ;
1074+ if ( func . type instanceof StringType ) return [ true , e . v ( code ) ] ;
1075+ }
1076+ return [ false , null ] ;
10651077 }
10661078
10671079 const [ left_string , left_reference ] = is_string_type ( left ) ;
@@ -1070,7 +1082,15 @@ function string_compare(left: Expression, right: Expression, operation: string,
10701082 if ( left_string || right_string ) {
10711083 const cmp = operation === "!=" ? "!=" : "==" ;
10721084 const r = left . context ( ) . R ( ) ;
1073- code . push ( `const int ${ r } = strcmp(${ left_reference } .data, ${ right_reference } .data) ${ cmp } 0;` ) ;
1085+ const left_sz = `${ left_reference } .sz` ;
1086+ const right_sz = `${ right_reference } .sz` ;
1087+ console . log ( right_reference ) ;
1088+ code . push (
1089+ `const int ${ r } = ` +
1090+ `${ left_sz } == ${ right_sz } ` +
1091+ `&& ` +
1092+ `memcmp(${ left_reference } .data, ${ right_reference } .data, ${ left_sz } ) ${ cmp } 0;`
1093+ ) ;
10741094 return r ;
10751095 }
10761096 return null ;
@@ -1291,6 +1311,8 @@ function expand_variable_reference(variable: Variable, variable_reference: Varia
12911311 let type : Type = variable . type ;
12921312 let reference = variable . name ;
12931313
1314+ const owner = { name : variable . name , type : variable . type } ;
1315+
12941316 for ( const part of variable_reference . parts ) {
12951317 if ( part instanceof VariableSubscript ) {
12961318 if ( type instanceof AliasType ) type = type . reference_type ;
@@ -1329,7 +1351,7 @@ function expand_variable_reference(variable: Variable, variable_reference: Varia
13291351 throw new GenerateError ( `unexpected variable reference part '${ part } ' at ${ variable . token } ` ) ;
13301352 }
13311353 }
1332- return { type, reference } ;
1354+ return { type, reference, owner } ;
13331355}
13341356
13351357function find_existing_variable ( v : VariableReference ) : Variable {
0 commit comments