Tristan B. V. Kildaire 4 weeks ago committed by GitHub
commit a05768e4b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

File diff suppressed because it is too large Load Diff

@ -240,12 +240,12 @@ public class Statement
public enum AccessorType
{
PUBLIC, PRIVATE, PROTECTED, UNKNOWN
UNKNOWN, PUBLIC, PRIVATE, PROTECTED
}
public enum InitScope
{
VIRTUAL, STATIC, UNKNOWN
UNKNOWN, VIRTUAL, STATIC
}
public class Assignment : Statement
@ -268,7 +268,7 @@ public class Assignment : Statement
public class Entity : Statement
{
/* Accessor type */
private AccessorType accessorType = AccessorType.PUBLIC;
private AccessorType accessorType;
/* Function/Modifier type */
private InitScope initScope;

@ -3,7 +3,7 @@ module tlang.compiler.typecheck.core;
import tlang.compiler.symbols.check;
import tlang.compiler.symbols.data;
import std.conv : to, ConvException;
import std.string;
import std.string : split, cmp, format;
import std.stdio;
import tlang.misc.logging;
import tlang.compiler.parsing.core;

@ -3,7 +3,7 @@ module tlang.compiler.typecheck.dependency.core;
import tlang.compiler.symbols.check;
import tlang.compiler.symbols.data;
import std.conv : to;
import std.string;
import std.string : cmp;
import std.stdio;
import tlang.misc.logging;
import tlang.compiler.parsing.core;
@ -12,7 +12,7 @@ import tlang.compiler.typecheck.exceptions;
import tlang.compiler.typecheck.core;
import tlang.compiler.symbols.typing.core;
import tlang.compiler.symbols.typing.builtins;
import tlang.compiler.typecheck.dependency.exceptions : DependencyException, DependencyError;
import tlang.compiler.typecheck.dependency.exceptions : DependencyException, DependencyError, AccessViolation;
import tlang.compiler.typecheck.dependency.pool.interfaces;
import tlang.compiler.typecheck.dependency.pool.impls;
import tlang.compiler.typecheck.dependency.store.interfaces : IFuncDefStore;
@ -451,6 +451,89 @@ public class DNodeGenerator
throw new DependencyException(DependencyError.GENERAL_ERROR, message);
}
/**
* Performs an access check to the given
* entity but from the accessing-environment
* of the provided statement
*
* Params:
* stmtCtx = the `Statement` to derive the
* access environment from
* referent = the `Entity` being referred
* to
* ignoreAccessModifiers = is we should
* ignore this check entirely (default: `false`)
* Returns: `true` if allowed, `false`
* otherwise
*/
private bool accessCheck
(
Statement stmtCtx, Entity referent,
bool ignoreAccessModifiers = false
)
{
// If ignoring mode then always allow accesses
if(ignoreAccessModifiers)
{
return true;
}
// Container of the accessing-environment
Container accCntnr = stmtCtx.parentOf();
// Container of the referent
Container refCntnr = referent.parentOf();
// If they are in the same container (exactly)
// then access should be allowed, irrespective
// of access modifiers
if(refCntnr == accCntnr)
{
return true;
}
// If the accessing-environment is in
// a container that is descendant
// of that of the referent's,
// in such a case access modifiers
// TOO can be ignored
else if(resolver.isDescendant(refCntnr, cast(Entity)accCntnr))
{
return true;
}
// If not, then base the check on access modifiers
else
{
// Obtain the access modifier of the referent
AccessorType accMod = referent.getAccessorType();
return referent.getAccessorType() == AccessorType.PUBLIC;
}
}
/**
* Throws an exception if there
* would be an access violation
* performing the given access
*
* See_Also: `accessCheck`
*/
private void accessCheckAuto
(
Statement stmtCtx, Entity referent,
bool ignoreAccessModifiers = false
)
{
if(accessCheck(stmtCtx, referent, ignoreAccessModifiers))
{
DEBUG("Access check passed for accEnv: ", stmtCtx, " with referentEnt: ", referent);
}
else
{
DEBUG("Access check FAILED for accEnv: ", stmtCtx, " with referentEnt: ", referent);
throw new AccessViolation(stmtCtx, referent);
}
}
public DNode root;
@ -619,6 +702,9 @@ public class DNodeGenerator
/* TODO: We need to fetch the cached function definition here and call it */
Entity funcEntity = resolver.resolveBest(context.container, funcCall.getName());
assert(funcEntity);
// Access check
accessCheckAuto(exp, funcEntity);
// FIXME: The below is failing (we probably need a forward look ahead?)
// OR use the addFuncDef list?
@ -724,6 +810,9 @@ public class DNodeGenerator
{
/* FIXME: Below assumes basic variable declarations at module level, fix later */
// Access check
accessCheckAuto(exp, namedEntity);
/**
* If `namedEntity` is a `Variable`
*

@ -2,6 +2,7 @@ module tlang.compiler.typecheck.dependency.exceptions;
import tlang.misc.exceptions : TError;
import std.conv : to;
import std.string : format;
// FIXME: Extend TError rather than Exception
public enum DependencyError
@ -25,4 +26,34 @@ public final class DependencyException : TError
{
return errTye;
}
}
/**
* An access violation occurs when you
* try to access one entity from an
* environment that doesn't allow
* for that due to the access rights
* of the referent entity
*/
public final class AccessViolation : TError
{
import tlang.compiler.symbols.data : Entity, Statement;
this
(
Statement env,
Entity referent
)
{
super
(
format
(
"Cannot access entity '%s' with access modifier %s from statement '%s'",
referent.getName(),
referent.getAccessorType(),
env
)
);
}
}

@ -4,7 +4,7 @@ import niks.c, b;
public ubyte j = 0;
int ident(int i)
private int ident(int i)
{
c.k();
return i;

@ -2,7 +2,7 @@ module b;
import a;
int doThing()
public int doThing()
{
int local = 0;

@ -2,7 +2,7 @@ module c;
import a;
void k()
public void k()
{
a.j = a.j + 2;
}
Loading…
Cancel
Save