From bf2be7deac1719934d04913dca4b7734f8ef2ad7 Mon Sep 17 00:00:00 2001 From: Mattia Giambirtone Date: Tue, 24 Jan 2023 12:19:06 +0100 Subject: [PATCH] Minor documentation changes --- src/frontend/compiler/compiler.nim | 6 +++++- src/frontend/compiler/targets/bytecode/target.nim | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/frontend/compiler/compiler.nim b/src/frontend/compiler/compiler.nim index dc7c135..41acbbf 100644 --- a/src/frontend/compiler/compiler.nim +++ b/src/frontend/compiler/compiler.nim @@ -827,9 +827,11 @@ method match*(self: Compiler, name: string, kind: Type, node: ASTNode = nil, all msg = &"call to undefined function '{name}'" self.error(msg, node) elif impl.len() > 1: + # If we happen to find more than one match, we try again + # and ignore forward declarations and automatic functions impl = filterIt(impl, not it.valueType.forwarded and not it.valueType.isAuto) if impl.len() > 1: - # If it's *still* more than one match, then it's an error + # If there's *still* more than one match, then it's an error var msg = &"multiple matching implementations of '{name}' found" if self.showMismatches: msg &= ":" @@ -838,6 +840,7 @@ method match*(self: Compiler, name: string, kind: Type, node: ASTNode = nil, all else: msg &= " (compile with --showMismatches for more details)" self.error(msg, node) + # This is only true when we're called by self.patchForwardDeclarations() if impl[0].valueType.forwarded and not allowFwd: self.error(&"expecting an implementation for function '{impl[0].ident.token.lexeme}' declared in module '{impl[0].owner.ident.token.lexeme}' at line {impl[0].ident.token.line} of type '{self.stringify(impl[0].valueType)}'") result = impl[0] @@ -1036,6 +1039,7 @@ proc declare*(self: Compiler, node: ASTNode): Name {.discardable.} = # We don't check for name clashes with functions because self.match() does that if name.kind in [NameKind.Var, NameKind.Module, NameKind.CustomType, NameKind.Enum] and name.depth == n.depth and name.owner == n.owner: self.error(&"re-declaration of {declaredName} is not allowed (previously declared in {name.owner.ident.token.lexeme}:{name.ident.token.line}:{name.ident.token.relPos.start})") + # We emit a bunch of warnings, mostly for QoL for name in self.names: if name == n: break diff --git a/src/frontend/compiler/targets/bytecode/target.nim b/src/frontend/compiler/targets/bytecode/target.nim index 121e649..c232058 100644 --- a/src/frontend/compiler/targets/bytecode/target.nim +++ b/src/frontend/compiler/targets/bytecode/target.nim @@ -589,10 +589,14 @@ proc endScope(self: BytecodeCompiler) = # Automatic functions do not materialize # at runtime, so their arguments don't either continue + # This name has been generated internally by the + # compiler and is a copy of an already existing + # one, so we only need to pop its "real" counterpart if not name.isReal: continue inc(popCount) if not name.resolved: + # We emit warnings for names that are declared but never used case name.kind: of NameKind.Var: if not name.ident.token.lexeme.startsWith("_") and name.isPrivate: @@ -681,7 +685,6 @@ proc unpackUnion(self: BytecodeCompiler, condition: Expression, list: var seq[tu self.error("invalid type constraint in type union", condition) - proc emitLoop(self: BytecodeCompiler, begin: int, line: int) = ## Emits a JumpBackwards instruction with the correct ## jump offset @@ -1644,6 +1647,8 @@ proc exportStmt(self: BytecodeCompiler, node: ExportStmt, compile: bool = true) for name in self.findInModule("", name): name.exportedTo.incl(self.parentModule) of NameKind.Function: + # Only exporting a single function (or, well + # all of its implementations) for name in self.findByName(name.ident.token.lexeme): if name.kind != NameKind.Function: continue @@ -1657,11 +1662,13 @@ proc breakStmt(self: BytecodeCompiler, node: BreakStmt) = ## to jump at the end of a loop or outside of a given ## block if node.label.isNil(): + # Jumping out of a loop self.currentLoop.breakJumps.add(self.emitJump(OpCode.JumpForwards, node.token.line)) if self.currentLoop.depth > self.depth: # Breaking out of a loop closes its scope self.endScope() else: + # Jumping out of a block var blocks: seq[NamedBlock] = @[] var found: bool = false for blk in reversed(self.namedBlocks): @@ -1709,9 +1716,15 @@ proc switchStmt(self: BytecodeCompiler, node: SwitchStmt) = var fn: Type var impl: Name var default: Expression + # Note that, unlike C switch statements, we don't + # cascade to other branches once the first one matches for branch in node.branches: + # We duplicate the top of the stack so we can safely + # pop the topmost expression without losing its value + # for later comparisons self.emitByte(DupTop, branch.body.token.line) self.expression(branch.cond) + # We look for a matching equality implementation fn = Type(kind: Function, returnType: Type(kind: Bool), args: @[("", typeOfA, default), ("", self.inferOrError(branch.cond), default)]) impl = self.match("==", fn, node) self.generateCall(impl, @[node.switch, branch.cond], impl.line)