-
Notifications
You must be signed in to change notification settings - Fork 7
Type hinting #116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Type hinting #116
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,8 @@ export class Token implements TokenBase { | |
| public readonly end: Position; | ||
| public readonly uri: string; | ||
|
|
||
| public ref: Maybe<Token>; | ||
|
|
||
| /** | ||
| * What symbol tracker is this token tied too | ||
| */ | ||
|
|
@@ -32,6 +34,7 @@ export class Token implements TokenBase { | |
| this.start = start; | ||
| this.end = end; | ||
| this.uri = uri; | ||
| this.ref = undefined; | ||
| this.tracker = undefined; | ||
| } | ||
|
|
||
|
|
@@ -57,6 +60,10 @@ export class Token implements TokenBase { | |
| }; | ||
| } | ||
|
|
||
| public get getRef(): Token | undefined { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably don't need this getter here since |
||
| return this.ref; | ||
| } | ||
|
|
||
| /** | ||
| * Convert the token to a human readable string | ||
| */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| import { Stmt, Block } from './stmt'; | ||
| import { IExpr, IStmtVisitor, ScopeKind, NodeDataBuilder } from '../types'; | ||
| import { ITypeHint, IExpr, IStmtVisitor, ScopeKind, NodeDataBuilder } from '../types'; | ||
| import { TokenType } from '../../models/tokentypes'; | ||
| import { empty, unWrap } from '../../utilities/typeGuards'; | ||
| import { Range, Position } from 'vscode-languageserver'; | ||
|
|
@@ -103,13 +103,15 @@ export class Var extends Decl { | |
| public readonly toIs: Token; | ||
| public readonly value: IExpr; | ||
| public readonly scope: Scope; | ||
| public readonly typeHint?: ITypeHint; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're applying
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I started with only parameters. constructor is using builder for subclasses, but not for superclass. Seems to be few issues just moving to to superclass. |
||
|
|
||
| constructor(builder: NodeDataBuilder<Var>) { | ||
| super(); | ||
| this.identifier = unWrap(builder.identifier); | ||
| this.toIs = unWrap(builder.toIs); | ||
| this.value = unWrap(builder.value); | ||
| this.scope = unWrap(builder.scope); | ||
| this.typeHint = builder.typeHint; | ||
| } | ||
|
|
||
| public toLines(): string[] { | ||
|
|
@@ -148,6 +150,7 @@ export class Lock extends Decl { | |
| public readonly to: Token; | ||
| public readonly value: IExpr; | ||
| public readonly scope?: Scope; | ||
| public readonly typeHint?: ITypeHint; | ||
|
|
||
| constructor(builder: NodeDataBuilder<Lock>) { | ||
| super(); | ||
|
|
@@ -156,6 +159,7 @@ export class Lock extends Decl { | |
| this.to = unWrap(builder.to); | ||
| this.value = unWrap(builder.value); | ||
| this.scope = builder.scope; | ||
| this.typeHint = builder.typeHint; | ||
| } | ||
|
|
||
| public toLines(): string[] { | ||
|
|
@@ -205,13 +209,15 @@ export class Func extends Decl { | |
| public readonly identifier: Token; | ||
| public readonly block: Block; | ||
| public readonly scope?: Scope; | ||
| public readonly typeHint?: ITypeHint; | ||
|
|
||
| constructor(builder: NodeDataBuilder<Func>) { | ||
| super(); | ||
| this.functionToken = unWrap(builder.functionToken); | ||
| this.identifier = unWrap(builder.identifier); | ||
| this.block = unWrap(builder.block); | ||
| this.scope = builder.scope; | ||
| this.typeHint = builder.typeHint; | ||
| } | ||
|
|
||
| public toLines(): string[] { | ||
|
|
@@ -254,13 +260,15 @@ export class Param extends Decl { | |
| public readonly requiredParameters: Parameter[]; | ||
| public readonly optionalParameters: DefaultParam[]; | ||
| public readonly scope?: Scope; | ||
| public readonly typeHint?: ITypeHint; | ||
|
|
||
| constructor(builder: NodeDataBuilder<Param>) { | ||
| super(); | ||
| this.parameterToken = unWrap(builder.parameterToken); | ||
| this.requiredParameters = unWrap(builder.requiredParameters); | ||
| this.optionalParameters = unWrap(builder.optionalParameters); | ||
| this.scope = builder.scope; | ||
| this.typeHint = builder.typeHint; | ||
| } | ||
|
|
||
| public toLines(): string[] { | ||
|
|
@@ -330,7 +338,10 @@ export class Param extends Decl { | |
| } | ||
|
|
||
| export class Parameter extends NodeBase { | ||
| constructor(public readonly identifier: Token) { | ||
| constructor( | ||
| public readonly identifier: Token, | ||
| public readonly typeHint?: Maybe<string>, | ||
| ) { | ||
| super(); | ||
| } | ||
|
|
||
|
|
@@ -360,8 +371,9 @@ export class DefaultParam extends Parameter { | |
| identifier: Token, | ||
| public readonly toIs: Token, | ||
| public readonly value: IExpr, | ||
| typeHint?: Maybe<string>, | ||
| ) { | ||
| super(identifier); | ||
| super(identifier, typeHint); | ||
| } | ||
|
|
||
| public toLines(): string[] { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ import { TokenType, isValidIdentifier } from '../models/tokentypes'; | |
| import { | ||
| IParseError, | ||
| IExpr, | ||
| ITypeHint, | ||
| IStmt, | ||
| INodeResult, | ||
| RunStmtType, | ||
|
|
@@ -42,6 +43,7 @@ export class Parser { | |
| private tokens: Token[]; | ||
| private current: number; | ||
| private runStmts: RunStmtType[]; | ||
| private types: Token[]; | ||
|
|
||
| private readonly andBind = this.and.bind(this); | ||
| private readonly eqaulityBind = this.equality.bind(this); | ||
|
|
@@ -57,13 +59,15 @@ export class Parser { | |
| tokens: Token[], | ||
| logger: ILogger = mockLogger, | ||
| tracer: ITracer = mockTracer, | ||
| types: Token[] = [], | ||
| ) { | ||
| this.uri = uri; | ||
| this.tokens = tokens.concat(this.eof(tokens)); | ||
| this.current = 0; | ||
| this.runStmts = []; | ||
| this.logger = logger; | ||
| this.tracer = tracer; | ||
| this.types = types; | ||
| } | ||
|
|
||
| // parse tokens | ||
|
|
@@ -75,6 +79,9 @@ export class Parser { | |
| this.logger.info( | ||
| `Parsing started for ${file} with ${this.tokens.length} tokens.`, | ||
| ); | ||
| this.logger.info( | ||
| `Parsing started for ${file} with ${this.types.length} tokens.`, | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe we could have something like |
||
| ); | ||
|
|
||
| const statements: Stmt.Stmt[] = []; | ||
| const parseDiagnostics: Diagnostic[] = []; | ||
|
|
@@ -242,9 +249,10 @@ export class Parser { | |
| } | ||
|
|
||
| // parse function declaration | ||
| private declareFunction(scope?: Decl.Scope): INodeResult<Decl.Func> { | ||
| private declareFunction(scope?: Decl.Scope, typeHint?: Maybe<ITypeHint>): INodeResult<Decl.Func> { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't appear anything is passed for |
||
| const builder: NodeDataBuilder<Decl.Func> = { | ||
| scope, | ||
| typeHint, | ||
| functionToken: undefined, | ||
| identifier: undefined, | ||
| block: undefined, | ||
|
|
@@ -261,6 +269,8 @@ export class Parser { | |
| if (this.matchToken(TokenType.curlyOpen)) { | ||
| const block = this.block(); | ||
| builder.block = block.value; | ||
|
|
||
| builder.typeHint = this.types.find(x => x.ref === builder.identifier)?.literal; | ||
|
|
||
| this.matchToken(TokenType.period); | ||
| return nodeResult(new Decl.Func(builder), block.errors); | ||
|
|
@@ -308,7 +318,8 @@ export class Parser { | |
| Decl.Parameter, | ||
| ); | ||
|
|
||
| parameters.push(new Decl.Parameter(identifer)); | ||
| const typeHint = this.types.find(x => x.ref === identifer); | ||
| parameters.push(new Decl.Parameter(identifer, typeHint?.literal)); | ||
| } while (this.matchToken(TokenType.comma)); | ||
|
|
||
| return parameters; | ||
|
|
@@ -333,8 +344,9 @@ export class Parser { | |
| [TokenType.to, TokenType.is], | ||
| ); | ||
| const valueResult = this.expression(); | ||
| const typeHint = this.types.find(x => x.ref === identifer); | ||
| defaultParameters.push( | ||
| new Decl.DefaultParam(identifer, toIs, valueResult.value), | ||
| new Decl.DefaultParam(identifer, toIs, valueResult.value, typeHint?.literal), | ||
| ); | ||
| errors.push(valueResult.errors); | ||
| } while (this.matchToken(TokenType.comma)); | ||
|
|
@@ -343,13 +355,14 @@ export class Parser { | |
| } | ||
|
|
||
| // parse lock statement | ||
| private declareLock(scope?: Decl.Scope): INodeResult<Decl.Lock> { | ||
| private declareLock(scope?: Decl.Scope, typeHint?: Maybe<ITypeHint>): INodeResult<Decl.Lock> { | ||
| const builder: NodeDataBuilder<Decl.Lock> = { | ||
| scope, | ||
| lock: undefined, | ||
| identifier: undefined, | ||
| value: undefined, | ||
| to: undefined, | ||
| typeHint, | ||
| }; | ||
|
|
||
| builder.lock = this.previous(); | ||
|
|
@@ -366,18 +379,21 @@ export class Parser { | |
| ); | ||
| const valueResult = this.expression(); | ||
| builder.value = valueResult.value; | ||
|
|
||
| builder.typeHint = this.types.find(x => x.ref === builder.identifier)?.literal; | ||
|
|
||
| this.terminal(Decl.Lock, builder); | ||
| return nodeResult(new Decl.Lock(builder), valueResult.errors); | ||
| } | ||
|
|
||
| // parse a variable declaration, scoping occurs elsewhere | ||
| private declareVariable(scope: Decl.Scope): INodeResult<Decl.Var> { | ||
| private declareVariable(scope: Decl.Scope, typeHint?: Maybe<ITypeHint>): INodeResult<Decl.Var> { | ||
| const builder: NodeDataBuilder<Decl.Var> = { | ||
| scope, | ||
| identifier: undefined, | ||
| value: undefined, | ||
| toIs: undefined, | ||
| typeHint, | ||
| }; | ||
|
|
||
| builder.identifier = this.consumeIdentifierThrow( | ||
|
|
@@ -395,6 +411,8 @@ export class Parser { | |
| const valueResult = this.expression(); | ||
| builder.value = valueResult.value; | ||
|
|
||
| builder.typeHint = this.types.find(x => x.ref === builder.identifier)?.literal; | ||
|
|
||
| this.terminal(Decl.Var, builder); | ||
| return nodeResult(new Decl.Var(builder), valueResult.errors); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we only set this in the scanner I think we should just update the constructor and make
refreadonly