// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
syntax = "proto2";
package luau;

message Expr {
	oneof expr_oneof {
		ExprGroup group = 1;
		ExprConstantNil nil = 2;
		ExprConstantBool bool = 3;
		ExprConstantNumber number = 4;
		ExprConstantString string = 5;
		ExprLocal local = 6;
		ExprGlobal global = 7;
		ExprVarargs varargs = 8;
		ExprCall call = 9;
		ExprIndexName index_name = 10;
		ExprIndexExpr index_expr = 11;
		ExprFunction function = 12;
		ExprTable table = 13;
		ExprUnary unary = 14;
		ExprBinary binary = 15;
		ExprIfElse ifelse = 16;
		ExprInterpString interpstring = 17;
	}
}

message ExprPrefix {
	oneof expr_oneof {
		ExprGroup group = 1;
		ExprLocal local = 2;
		ExprGlobal global = 3;
		ExprCall call = 4;
		ExprIndexName index_name = 5;
		ExprIndexExpr index_expr = 6;
	}
}

message Local {
	required int32 name = 1;
}

message Typename {
	required int32 index = 1;
}

message Name {
	oneof name_oneof {
		int32 builtin = 1;
		int32 custom = 2;
	}
}

message ExprGroup {
	required Expr expr = 1;
}

message ExprConstantNil {
}

message ExprConstantBool {
	required bool val = 1;
}

message ExprConstantNumber {
	required int32 val = 1;
}

message ExprConstantString {
	required string val = 1;
}

message ExprLocal {
	required Local var = 1;
}

message ExprGlobal {
	required Name name = 1;
}

message ExprVarargs {
}

message ExprCall {
	required ExprPrefix func = 1;
	required bool self = 2;
	repeated Expr args = 3;
}

message ExprIndexName {
	required ExprPrefix expr = 1;
	required Name index = 2;
}

message ExprIndexExpr {
	required ExprPrefix expr = 1;
	required Expr index = 2;
}

message ExprFunction {
	repeated Typename generics = 1;
	repeated Typename genericpacks = 2;
	repeated Local args = 3;
	required bool vararg = 4;
	required StatBlock body = 5;
	repeated Type types = 6;
	repeated Type rettypes = 7;
}

message TableItem {
	oneof item_oneof {
		Name key_name = 1;
		Expr key_expr = 2;
	}
	required Expr value = 3;
}

message ExprTable {
	repeated TableItem items = 1;
}

message ExprUnary {
	enum Op {
		Not = 0;
		Minus = 1;
		Len = 2;
	}

	required Op op = 1;
	required Expr expr = 2;
}

message ExprBinary {
	enum Op {
        Add = 0;
        Sub = 1;
        Mul = 2;
        Div = 3;
        FloorDiv = 4;
        Mod = 5;
        Pow = 6;
        Concat = 7;
        CompareNe = 8;
        CompareEq = 9;
        CompareLt = 10;
        CompareLe = 11;
        CompareGt = 12;
        CompareGe = 13;
        And = 14;
        Or = 15;
	}

	required Op op = 1;
	required Expr left = 2;
	required Expr right = 3;
}

message ExprIfElse {
	required Expr cond = 1;
	required Expr then = 2;
	oneof else_oneof {
		Expr else = 3;
		ExprIfElse elseif = 4;
	}
}

message ExprInterpString {
	repeated Expr parts = 1;
}

message LValue {
	oneof lvalue_oneof {
		ExprLocal local = 1;
		ExprGlobal global = 2;
		ExprIndexName index_name = 3;
		ExprIndexExpr index_expr = 4;
	}
}

message Stat {
	oneof stat_oneof {
		StatBlock block = 1;
		StatIf if = 2;
		StatWhile while = 3;
		StatRepeat repeat = 4;
		StatBreak break = 5;
		StatContinue continue = 6;
		StatReturn return = 7;
		StatCall call = 8;
		StatLocal local = 9;
		StatFor for = 10;
		StatForIn for_in = 11;
		StatAssign assign = 12;
		StatCompoundAssign compound_assign = 13;
		StatFunction function = 14;
		StatLocalFunction local_function = 15;
		StatTypeAlias type_alias = 16;
		StatRequireIntoLocalHelper require_into_local = 17;
	}
}

message StatBlock {
	repeated Stat body = 1;
}

message StatIf {
	required Expr cond = 1;
	required StatBlock then = 2;
	oneof else_oneof {
		StatBlock else = 3;
		StatIf elseif = 4;
	}
}

message StatWhile {
	required Expr cond = 1;
	required StatBlock body = 2;
}

message StatRepeat {
	required StatBlock body = 1;
	required Expr cond = 2;
}

message StatBreak {
}

message StatContinue {
}

message StatReturn {
	repeated Expr list = 1;
}

message StatCall {
	required ExprCall expr = 1;
}

message StatLocal {
	repeated Local vars = 1;
	repeated Expr values = 2;
	repeated Type types = 3;
}

message StatFor {
	required Local var = 1;
	required Expr from = 2;
	required Expr to = 3;
	optional Expr step = 4;
	required StatBlock body = 5;
}

message StatForIn {
	repeated Local vars = 1;
	repeated Expr values = 2;
	required StatBlock body = 5;
}

message StatAssign {
	repeated LValue vars = 1;
	repeated Expr values = 2;
}

message StatCompoundAssign {
	enum Op {
        Add = 0;
        Sub = 1;
        Mul = 2;
        Div = 3;
        Mod = 4;
        Pow = 5;
        Concat = 6;
	};

	required Op op = 1;
	required LValue var = 2;
	required Expr value = 3;
}

message StatFunction {
	required LValue var = 1;
	required ExprFunction func = 2;
	required bool self = 3;
}

message StatLocalFunction {
	required Local var = 1;
	required ExprFunction func = 2;
}

message StatTypeAlias {
	required bool export = 1;
	required Typename name = 2;
	required Type type = 3;
	repeated Typename generics = 4;
	repeated Typename genericpacks = 5;
}

message StatRequireIntoLocalHelper {
	required Local var = 1;
	required int32 modulenum = 2;
}

message Type {
	oneof type_oneof {
		TypePrimitive primitive = 1;
		TypeLiteral literal = 2;
		TypeTable table = 3;
		TypeFunction function = 4;
		TypeTypeof typeof = 5;
		TypeUnion union = 6;
		TypeIntersection intersection = 7;
		TypeClass class = 8;
		TypeRef ref = 9;
		TypeBoolean boolean = 10;
		TypeString string = 11;
	}
}

message TypePrimitive {
	required int32 kind = 1;
}

message TypeLiteral {
	required Typename name = 1;
	repeated Type generics = 2;
	repeated Typename genericpacks = 3;
}

message TypeTableItem {
	required Name key = 1;
	required Type type = 2;
}

message TypeTableIndexer {
	required Type key = 1;
	required Type value = 2;
}

message TypeTable {
	repeated TypeTableItem items = 1;
	optional TypeTableIndexer indexer = 2;
}

message TypeFunction {
	repeated Typename generics = 1;
	repeated Typename genericpacks = 2;
	repeated Type args = 3;
	repeated Type rets = 4;
	// TODO: vararg?
}

message TypeTypeof {
	required Expr expr = 1;
}

message TypeUnion {
	required Type left = 1;
	required Type right = 2;
}

message TypeIntersection {
	required Type left = 1;
	required Type right = 2;
}

message TypeClass {
	required int32 kind = 1;
}

message TypeRef {
	required Local prefix = 1;
	required Typename index = 2;
}

message TypeBoolean {
	required bool val = 1;
}

message TypeString {
	required string val = 1;
}

message ModuleSet {
	optional StatBlock module = 1;
	required StatBlock program = 2;
}
