Skip to content

Commit e2e6b29

Browse files
Merged pull request #18 from 'feature/free'.
Free statement
2 parents 719f674 + 2c02ec2 commit e2e6b29

File tree

19 files changed

+157
-2
lines changed

19 files changed

+157
-2
lines changed

examples/memoryManagement/main.ph

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module MemoryManagementExample;
2+
3+
import Standard.Io;
4+
5+
function main ()
6+
{
7+
let myArray := new Array[String](3);
8+
myArray.set(1, 'Initialisation succeeded.');
9+
10+
Io.writeLine(myArray.get(1));
11+
12+
free myArray;
13+
14+
Io.writeLine('Segmentation fault should follow...');
15+
16+
Io.writeLine(myArray.get(1));
17+
}

src/connector/connector.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,8 @@ export class Connector
789789
return this.connectAssignment(statement, context);
790790
case SyntaxKind.CallExpression:
791791
return this.connectCallExpression(statement, context);
792+
case SyntaxKind.FreeStatement:
793+
return this.connectFreeStatement(statement, context);
792794
case SyntaxKind.Section:
793795
return this.connectSection(statement, context);
794796
case SyntaxKind.LocalVariableDeclaration:
@@ -967,6 +969,24 @@ export class Connector
967969
return new SemanticNodes.WhileStatement(condition, section);
968970
}
969971

972+
private connectFreeStatement (freeStatement: SyntaxNodes.FreeStatement, context: FunctionContext): SemanticNodes.FreeStatement
973+
{
974+
const expression = this.connectExpression(freeStatement.expression, context);
975+
976+
if (BuildInTypes.isBuildInType(expression.type) && !BuildInTypes.isArray(expression.type))
977+
{
978+
this.diagnostic.throw(
979+
new Diagnostic.Error(
980+
`Cannot free the non-reference type "${expression.type.namespace.baseName}".`,
981+
Diagnostic.Codes.FreeNonReferenceTypeError,
982+
freeStatement.expression.token
983+
)
984+
);
985+
}
986+
987+
return new SemanticNodes.FreeStatement(expression);
988+
}
989+
970990
private connectAssignment (assignment: SyntaxNodes.Assignment, context: FunctionContext): SemanticNodes.Assignment
971991
{
972992
const namespace = Namespace.constructFromNamespace(context.module.namespace, assignment.identifier.content);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { SemanticKind } from '../semanticKind';
2+
3+
export class FreeStatementGenericNode <Expression>
4+
{
5+
public readonly kind: SemanticKind.FreeStatement;
6+
7+
public readonly expression: Expression;
8+
9+
constructor (expression: Expression)
10+
{
11+
this.kind = SemanticKind.FreeStatement;
12+
13+
this.expression = expression;
14+
}
15+
}

src/connector/genericNodes/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export { ElseClauseGenericNode as ElseClause } from './elseClauseGenericNode';
1111
export { FieldDeclarationGenericNode as FieldDeclaration } from './fieldDeclarationGenericNode';
1212
export { FieldExpressionGenericNode as FieldExpression } from './fieldExpressionGenericNode';
1313
export { FileGenericNode as File } from './fileGenericNode';
14+
export { FreeStatementGenericNode as FreeStatement } from './freeStatementGenericNode';
1415
export { FunctionDeclarationGenericNode as FunctionDeclaration } from './functionDeclarationGenericNode';
1516
export { GlobalVariableDeclarationGenericNode as GlobalVariableDeclaration } from './globalVariableDeclarationGenericNode';
1617
export { IfStatementGenericNode as IfStatement } from './ifStatementGenericNode';
@@ -34,6 +35,7 @@ import { ElseClauseGenericNode } from './elseClauseGenericNode';
3435
import { FieldDeclarationGenericNode } from './fieldDeclarationGenericNode';
3536
import { FieldExpressionGenericNode } from './fieldExpressionGenericNode';
3637
import { FileGenericNode } from './fileGenericNode';
38+
import { FreeStatementGenericNode } from './freeStatementGenericNode';
3739
import { FunctionDeclarationGenericNode } from './functionDeclarationGenericNode';
3840
import { GlobalVariableDeclarationGenericNode } from './globalVariableDeclarationGenericNode';
3941
import { IfStatementGenericNode } from './ifStatementGenericNode';
@@ -71,6 +73,7 @@ export type GenericNode<
7173
| FieldDeclarationGenericNode<Expression, TypeLikeSymbol>
7274
| FieldExpressionGenericNode<Expression, TypeLikeSymbol>
7375
| FileGenericNode<GlobalVariableDeclaration, FieldDeclaration, FunctionDeclaration, ClassTypeSymbol, TypeLikeSymbol>
76+
| FreeStatementGenericNode<Expression>
7477
| FunctionDeclarationGenericNode<Section, TypeLikeSymbol>
7578
| GlobalVariableDeclarationGenericNode<Expression, TypeLikeSymbol>
7679
| IfStatementGenericNode<Expression, Section, ElseClause>
@@ -87,6 +90,7 @@ export type GenericStatement<Expression, Statement, Section, ElseClause, Variabl
8790
ArraySetExpressionGenericNode<Expression, TypeLikeSymbol>
8891
| AssignmentGenericNode<Expression, FieldExpression, VariableExpression>
8992
| CallExpressionGenericNode<Expression, TypeLikeSymbol>
93+
| FreeStatementGenericNode<Expression>
9094
| IfStatementGenericNode<Expression, Section, ElseClause>
9195
| LocalVariableDeclarationGenericNode<Expression, TypeLikeSymbol>
9296
| ReturnStatementGenericNode<Expression>

src/connector/semanticKind.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export enum SemanticKind
1616
LocalVariableDeclaration = 'LocalVariableDeclaration',
1717
GlobalVariableDeclaration = 'GlobalVariableDeclaration',
1818
FieldDeclaration = 'FieldDeclaration',
19+
FreeStatement = 'FreeStatement',
1920
// Expressions
2021
LiteralExpression = 'LiteralExpression',
2122
InstantiationExpression = 'InstantiationExpression',

src/connector/semanticNodes/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export class File extends GenericNodes.File<
1717
SemanticSymbols.GenericType,
1818
SemanticSymbols.TypeLike
1919
> {}
20+
export class FreeStatement extends GenericNodes.FreeStatement<Expression> {}
2021
export class FunctionDeclaration extends GenericNodes.FunctionDeclaration<Section, SemanticSymbols.TypeLike> {}
2122
export class GlobalVariableDeclaration extends GenericNodes.GlobalVariableDeclaration<Expression, SemanticSymbols.TypeLike> {}
2223
export class IfStatement extends GenericNodes.IfStatement<Expression, Section, ElseClause> {}
@@ -37,6 +38,7 @@ export type SemanticNode =
3738
| ElseClause
3839
| FieldExpression
3940
| File
41+
| FreeStatement
4042
| FunctionDeclaration
4143
| GlobalVariableDeclaration
4244
| FieldDeclaration
@@ -55,6 +57,7 @@ export type Statement =
5557
ArraySetExpression
5658
| Assignment
5759
| CallExpression
60+
| FreeStatement
5861
| IfStatement
5962
| LocalVariableDeclaration
6063
| ReturnStatement

src/definitions/buildInFunctions.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,17 @@ export abstract class BuildInFunctions
4242
null,
4343
true
4444
);
45+
46+
public static readonly free = new SpecialisedSymbols.Function(
47+
Namespace.constructFromStrings('Standard', 'Memory', 'free'),
48+
BuildInTypes.noType,
49+
[
50+
new SpecialisedSymbols.FunctionParameter(
51+
Namespace.constructFromStrings('Standard', 'Memory', 'free', 'pointer'),
52+
BuildInTypes.pointer
53+
)
54+
],
55+
null,
56+
true
57+
);
4558
}

src/definitions/buildInModules.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ export abstract class BuildInModules
2424
new Map(),
2525
new Map(
2626
[
27-
[BuildInFunctions.allocate.namespace.qualifiedName, BuildInFunctions.allocate]
27+
[BuildInFunctions.allocate.namespace.qualifiedName, BuildInFunctions.allocate],
28+
[BuildInFunctions.free.namespace.qualifiedName, BuildInFunctions.free]
2829
]
2930
),
3031
false

src/diagnostic/diagnosticCodes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export enum DiagnosticCodes // TODO: Should this be singular?
7676
UnexpectedTokenInGenericsDeclarationError = 'E1077',
7777
NonGenericTypeIsUsedAsGenericTypeError = 'E1078',
7878
UnknownArrayAccessError = 'E1079',
79+
FreeNonReferenceTypeError = 'E1080',
7980
// Warnings:
8081
ExperimentalPlatformWarning = 'W1001',
8182
// Infos:

src/lexer/lexer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,9 @@ export class Lexer
411411
case 'new':
412412
kind = TokenKind.NewKeyword;
413413
break;
414+
case 'free':
415+
kind = TokenKind.FreeKeyword;
416+
break;
414417
case 'variable':
415418
kind = TokenKind.VariableKeyword;
416419
break;

0 commit comments

Comments
 (0)